import type { GiteaIssue, GiteaRepo } from './shared';
import { useState } from 'react';
import { Link } from 'react-router';
import { ArrowLeft, ExternalLink, MessageSquare } from 'lucide-react';
import { DataRow, RelativeTime } from '@/components/Data';
import { Avatar, EmptyState, ErrorState, LabelChip, Loading, StateBadge, StateFilter, StateIcon } from './GiteaBits';
import { GiteaMarkdown } from './GiteaMarkdown';
import { giteaRepoPath } from './shared';
import { useGiteaIssue, useGiteaIssueComments, useGiteaRepoIssues } from './useGiteaData';

// Issues for one repository — the list, and one issue with its comment timeline.
//
// `type` is a prop rather than two copies of this file because in Gitea a pull request IS an issue: same
// number space, same list endpoint, same comment timeline. Only the extra PR data (branches, changed files)
// needs its own screen, which is RepoPullsView.

type RepoIssuesViewProps = {
  repo: GiteaRepo;
  owner: string;
  name: string;
  /** Issue number from the URL, or null for the list. */
  item: string | null;
  type?: 'issues' | 'pulls';
};

export const RepoIssuesView = ({ repo, owner, name, item, type = 'issues' }: RepoIssuesViewProps) => {
  const index = item ? Number(item) : null;
  if (index != null && Number.isFinite(index)) {
    return <IssueDetail repo={repo} owner={owner} name={name} index={index} type={type} />;
  }
  return <IssueList repo={repo} owner={owner} name={name} type={type} />;
};

// ── List ──────────────────────────────────────────────────────────────────────────────────────────

type ListProps = { repo: GiteaRepo; owner: string; name: string; type: 'issues' | 'pulls' };

const IssueList = ({ owner, name, type }: ListProps) => {
  // The open/closed filter is component state rather than a URL param: it is a view preference over a list
  // that is itself the addressable thing, and putting it in the URL would make every filter click a history
  // entry to press back through.
  const [state, setState] = useState<'open' | 'closed' | 'all'>('open');
  const { data: issues, isLoading, error } = useGiteaRepoIssues({ owner, repo: name }, { state, type });

  const noun = type === 'pulls' ? 'pull requests' : 'issues';

  return (
    <div className="flex h-full flex-col">
      <div className="flex items-center gap-3 border-b px-4 py-2">
        <StateFilter value={state} onChange={setState} />
        {!!issues?.length && (
          <span className="text-xs tabular-nums text-muted-foreground">
            {issues.length} {noun}
          </span>
        )}
      </div>
      <div className="min-h-0 flex-1 overflow-y-auto">
        {isLoading ? (
          <Loading label={`Loading ${noun}…`} />
        ) : error ? (
          <ErrorState title={`Could not load ${noun}`} error={error} />
        ) : !issues?.length ? (
          <EmptyState
            title={`No ${state === 'all' ? '' : state} ${noun}`.replace(/\s+/g, ' ').trim()}
            hint={
              state === 'open'
                ? `Closed ${noun} are hidden by this filter — switch to closed or all to see them.`
                : `This repository has no ${noun}.`
            }
          />
        ) : (
          <div className="divide-y">
            {issues.map((issue) => (
              <IssueRow key={issue.id} issue={issue} owner={owner} name={name} type={type} />
            ))}
          </div>
        )}
      </div>
    </div>
  );
};

type RowProps = { issue: GiteaIssue; owner: string; name: string; type: 'issues' | 'pulls' };

const IssueRow = ({ issue, owner, name, type }: RowProps) => (
  <DataRow
    to={giteaRepoPath(owner, name, { tab: type === 'pulls' ? 'pulls' : 'issues', item: issue.number })}
    lead={<StateIcon item={issue} />}
    title={
      <>
        {/* Truncates rather than wrapping, so labels stay visible and every row keeps one height —
            a list of uneven rows cannot be scanned down its left edge. */}
        <span className="truncate text-sm font-medium">{issue.title}</span>
        {issue.labels?.map((label) => (
          <LabelChip key={label.id} label={label} />
        ))}
      </>
    }
    meta={[
      `#${issue.number}`,
      <RelativeTime value={issue.created_at} prefix="opened" />,
      issue.user && `by ${issue.user.login}`,
    ]}
    trail={
      !!issue.comments && (
        <span className="flex items-center gap-1.5 text-xs tabular-nums text-muted-foreground">
          <MessageSquare className="h-3.5 w-3.5" />
          {issue.comments}
        </span>
      )
    }
  />
);

// ── Detail ────────────────────────────────────────────────────────────────────────────────────────

type DetailProps = { repo: GiteaRepo; owner: string; name: string; index: number; type: 'issues' | 'pulls' };

const IssueDetail = ({ repo, owner, name, index, type }: DetailProps) => {
  const { data: issue, isLoading, error } = useGiteaIssue({ owner, repo: name }, index);
  const { data: comments } = useGiteaIssueComments({ owner, repo: name }, index);

  if (isLoading) return <Loading label={`Loading #${index}…`} />;
  if (error) return <ErrorState title={`Could not load #${index}`} error={error} />;
  if (!issue) return <EmptyState title={`#${index} not found`} />;

  return (
    <div className="h-full overflow-y-auto">
      <IssueHeader issue={issue} owner={owner} name={name} type={type} />

      <div className="flex flex-col gap-3 px-4 pb-6">
        <CommentCard
          author={issue.user}
          createdAt={issue.created_at}
          body={issue.body}
          repo={repo}
          emptyText="No description provided."
        />
        {comments?.map((comment) => (
          <CommentCard
            key={comment.id}
            author={comment.user}
            createdAt={comment.created_at}
            body={comment.body}
            repo={repo}
          />
        ))}
      </div>
    </div>
  );
};

type HeaderProps = { issue: GiteaIssue; owner: string; name: string; type: 'issues' | 'pulls' };

const IssueHeader = ({ issue, owner, name, type }: HeaderProps) => (
  <div className="border-b px-4 py-3">
    <Link
      to={giteaRepoPath(owner, name, { tab: type === 'pulls' ? 'pulls' : 'issues' })}
      className="mb-2 inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground"
    >
      <ArrowLeft className="h-3 w-3" />
      Back to {type === 'pulls' ? 'pull requests' : 'issues'}
    </Link>
    <div className="flex items-start gap-2">
      <h2 className="min-w-0 flex-1 text-base font-semibold leading-snug">
        {issue.title} <span className="font-normal text-muted-foreground">#{issue.number}</span>
      </h2>
      <a
        href={issue.html_url}
        target="_blank"
        rel="noreferrer"
        className="shrink-0 text-muted-foreground hover:text-foreground"
        title="Open in Gitea"
      >
        <ExternalLink className="h-4 w-4" />
      </a>
    </div>
    <div className="mt-2 flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
      <StateBadge item={issue} />
      <span>
        {issue.user?.login ?? 'someone'} opened this <RelativeTime value={issue.created_at} /> · {issue.comments}{' '}
        comments
      </span>
      {issue.labels?.map((label) => (
        <LabelChip key={label.id} label={label} />
      ))}
    </div>
    {!!issue.assignees?.length && (
      <div className="mt-2 flex items-center gap-1.5 text-xs text-muted-foreground">
        <span>Assigned to</span>
        {issue.assignees.map((user) => (
          <span key={user.id} className="flex items-center gap-1">
            <Avatar user={user} size={16} />
            {user.login}
          </span>
        ))}
      </div>
    )}
  </div>
);

type CommentProps = {
  author?: GiteaIssue['user'];
  createdAt: string;
  body?: string;
  repo: GiteaRepo;
  emptyText?: string;
};

export const CommentCard = ({ author, createdAt, body, repo, emptyText }: CommentProps) => (
  <div className="overflow-hidden rounded-lg border">
    <div className="flex items-center gap-2 border-b bg-muted/40 px-3 py-2 text-xs">
      <Avatar user={author} size={18} />
      <span className="font-medium">{author?.login ?? 'unknown'}</span>
      <span className="text-muted-foreground">
        commented <RelativeTime value={createdAt} />
      </span>
    </div>
    <div className="px-3 py-2">
      {body?.trim() ? (
        <GiteaMarkdown content={body} repoUrl={repo.html_url} refName={repo.default_branch ?? 'main'} />
      ) : (
        <p className="text-sm italic text-muted-foreground">{emptyText ?? 'No content.'}</p>
      )}
    </div>
  </div>
);
