"use client";

import { useState, useMemo } from "react";
import Link from "next/link";
import { Row, Col, Card, Table, Badge, Alert, Button } from "react-bootstrap";
import ZxdbBreadcrumbs from "@/app/zxdb/components/ZxdbBreadcrumbs";
import FileViewer from "@/components/FileViewer";

type ReleaseDetailData = {
  entry: {
    id: number;
    title: string;
    issueId: number | null;
  };
  entryReleases: Array<{
    releaseSeq: number;
    year: number | null;
  }>;
  release: {
    entryId: number;
    releaseSeq: number;
    year: number | null;
    month: number | null;
    day: number | null;
    currency: { id: string | null; name: string | null; symbol: string | null; prefix: number | null };
    prices: {
      release: number | null;
      budget: number | null;
      microdrive: number | null;
      disk: number | null;
      cartridge: number | null;
    };
    book: { isbn: string | null; pages: number | null };
  };
  downloads: Array<{
    id: number;
    link: string;
    size: number | null;
    md5: string | null;
    comments: string | null;
    isDemo: boolean;
    type: { id: number; name: string };
    language: { id: string | null; name: string | null };
    machinetype: { id: number | null; name: string | null };
    scheme: { id: string | null; name: string | null };
    source: { id: string | null; name: string | null };
    case: { id: string | null; name: string | null };
    year: number | null;
    localLink?: string | null;
  }>;
  scraps: Array<{
    id: number;
    link: string | null;
    size: number | null;
    comments: string | null;
    rationale: string;
    isDemo: boolean;
    type: { id: number; name: string };
    language: { id: string | null; name: string | null };
    machinetype: { id: number | null; name: string | null };
    scheme: { id: string | null; name: string | null };
    source: { id: string | null; name: string | null };
    case: { id: string | null; name: string | null };
    year: number | null;
    localLink?: string | null;
  }>;
  files: Array<{
    id: number;
    link: string;
    size: number | null;
    md5: string | null;
    comments: string | null;
    type: { id: number; name: string };
  }>;
  magazineRefs: Array<{
    id: number;
    issueId: number;
    magazineId: number | null;
    magazineName: string | null;
    referencetypeId: number;
    referencetypeName: string | null;
    page: number;
    isOriginal: number;
    scoreGroup: string;
    issue: {
      dateYear: number | null;
      dateMonth: number | null;
      dateDay: number | null;
      volume: number | null;
      number: number | null;
      special: string | null;
      supplement: string | null;
    };
  }>;
};

function formatIssue(issue: ReleaseDetailData["magazineRefs"][number]["issue"]) {
  const parts: string[] = [];
  if (issue.volume != null) parts.push(`v.${issue.volume}`);
  if (issue.number != null) parts.push(`#${issue.number}`);
  if (issue.dateYear != null) {
    let date = `${issue.dateYear}`;
    if (issue.dateMonth != null) {
      const mm = String(issue.dateMonth).padStart(2, "0");
      date += `/${mm}`;
      if (issue.dateDay != null) {
        const dd = String(issue.dateDay).padStart(2, "0");
        date += `/${dd}`;
      }
    }
    parts.push(date);
  }
  if (issue.special) parts.push(`special "${issue.special}"`);
  if (issue.supplement) parts.push(`supplement "${issue.supplement}"`);
  return parts.join(" ");
}

function formatCurrency(value: number | null, currency: ReleaseDetailData["release"]["currency"]) {
  if (value == null) return "-";
  if (currency.symbol) {
    return currency.prefix ? `${currency.symbol}${value}` : `${value}${currency.symbol}`;
  }
  if (currency.name) return `${value} ${currency.name}`;
  return String(value);
}

type MagazineGroup = {
  magazineId: number | null;
  magazineName: string | null;
  items: ReleaseDetailData["magazineRefs"];
};

type IssueGroup = {
  issueId: number;
  issue: ReleaseDetailData["magazineRefs"][number]["issue"];
  items: ReleaseDetailData["magazineRefs"];
};

function groupMagazineRefs(refs: ReleaseDetailData["magazineRefs"]) {
  const groups: MagazineGroup[] = [];
  const lookup = new Map<string, MagazineGroup>();

  for (const ref of refs) {
    const key = ref.magazineId != null ? `mag:${ref.magazineId}` : "mag:unknown";
    let group = lookup.get(key);
    if (!group) {
      group = { magazineId: ref.magazineId, magazineName: ref.magazineName, items: [] };
      lookup.set(key, group);
      groups.push(group);
    }
    group.items.push(ref);
  }

  return groups;
}

function groupIssueRefs(refs: ReleaseDetailData["magazineRefs"]) {
  const groups: IssueGroup[] = [];
  const lookup = new Map<number, IssueGroup>();

  for (const ref of refs) {
    const key = ref.issueId;
    let group = lookup.get(key);
    if (!group) {
      group = { issueId: ref.issueId, issue: ref.issue, items: [] };
      lookup.set(key, group);
      groups.push(group);
    }
    group.items.push(ref);
  }

  return groups;
}

export default function ReleaseDetailClient({ data }: { data: ReleaseDetailData | null }) {
  const [viewer, setViewer] = useState<{ url: string; title: string } | null>(null);

  const groupedDownloads = useMemo(() => {
    if (!data?.downloads) return [];
    const groups = new Map<string, ReleaseDetailData["downloads"]>();
    for (const d of data.downloads) {
      const type = d.type.name;
      const arr = groups.get(type) ?? [];
      arr.push(d);
      groups.set(type, arr);
    }
    return Array.from(groups.entries()).sort((a, b) => a[0].localeCompare(b[0]));
  }, [data?.downloads]);

  const groupedScraps = useMemo(() => {
    if (!data?.scraps) return [];
    const groups = new Map<string, ReleaseDetailData["scraps"]>();
    for (const s of data.scraps) {
      const type = s.type.name;
      const arr = groups.get(type) ?? [];
      arr.push(s);
      groups.set(type, arr);
    }
    return Array.from(groups.entries()).sort((a, b) => a[0].localeCompare(b[0]));
  }, [data?.scraps]);

  if (!data) return <Alert variant="warning">Not found</Alert>;

  const magazineGroups = groupMagazineRefs(data.magazineRefs);
  const otherReleases = data.entryReleases.filter((r) => r.releaseSeq !== data.release.releaseSeq);

  return (
    <div>
      <ZxdbBreadcrumbs
        items={[
          { label: "ZXDB", href: "/zxdb" },
          { label: "Releases", href: "/zxdb/releases" },
          { label: data.entry.title, href: `/zxdb/entries/${data.entry.id}` },
          { label: `Release #${data.release.releaseSeq}` },
        ]}
      />

      <div className="d-flex align-items-center gap-2 flex-wrap">
        <h1 className="mb-0">Release #{data.release.releaseSeq}</h1>
        <Link href={`/zxdb/entries/${data.entry.id}`} className="text-decoration-none">
          <Badge bg="secondary">{data.entry.title}</Badge>
        </Link>
      </div>

      <Row className="g-3 mt-2">
        <Col lg={4}>
          <Card className="shadow-sm mb-3">
            <Card.Body>
              <Card.Title>Release Summary</Card.Title>
              <Table size="sm" striped className="align-middle mb-0">
                  <tbody>
                    <tr>
                      <th style={{ width: 160 }}>Entry</th>
                      <td>
                        <Link href={`/zxdb/entries/${data.entry.id}`}>#{data.entry.id}</Link>
                      </td>
                    </tr>
                    <tr>
                      <th>Release Sequence</th>
                      <td>#{data.release.releaseSeq}</td>
                    </tr>
                    <tr>
                      <th>Release Date</th>
                      <td>
                        {data.release.year != null ? (
                          <span>
                            {data.release.year}
                            {data.release.month != null ? `/${String(data.release.month).padStart(2, "0")}` : ""}
                            {data.release.day != null ? `/${String(data.release.day).padStart(2, "0")}` : ""}
                          </span>
                        ) : (
                          <span className="text-secondary">-</span>
                        )}
                      </td>
                    </tr>
                    <tr>
                      <th>Currency</th>
                      <td>
                        {data.release.currency.id ? (
                          <span>{data.release.currency.id} {data.release.currency.name ? `(${data.release.currency.name})` : ""}</span>
                        ) : (
                          <span className="text-secondary">-</span>
                        )}
                      </td>
                    </tr>
                    <tr>
                      <th>Price</th>
                      <td>{formatCurrency(data.release.prices.release, data.release.currency)}</td>
                    </tr>
                    <tr>
                      <th>Budget Price</th>
                      <td>{formatCurrency(data.release.prices.budget, data.release.currency)}</td>
                    </tr>
                    <tr>
                      <th>Microdrive Price</th>
                      <td>{formatCurrency(data.release.prices.microdrive, data.release.currency)}</td>
                    </tr>
                    <tr>
                      <th>Disk Price</th>
                      <td>{formatCurrency(data.release.prices.disk, data.release.currency)}</td>
                    </tr>
                    <tr>
                      <th>Cartridge Price</th>
                      <td>{formatCurrency(data.release.prices.cartridge, data.release.currency)}</td>
                    </tr>
                    <tr>
                      <th>Book ISBN</th>
                      <td>{data.release.book.isbn ?? <span className="text-secondary">-</span>}</td>
                    </tr>
                    <tr>
                      <th>Book Pages</th>
                      <td>{data.release.book.pages ?? <span className="text-secondary">-</span>}</td>
                    </tr>
                  </tbody>
              </Table>
            </Card.Body>
          </Card>

          <Card className="shadow-sm">
            <Card.Body>
              <Card.Title>Other Releases</Card.Title>
              {otherReleases.length === 0 && <div className="text-secondary">No other releases</div>}
              {otherReleases.length > 0 && (
                <div className="d-flex flex-wrap gap-2">
                  {otherReleases.map((r) => (
                    <Link
                      key={r.releaseSeq}
                      href={`/zxdb/releases/${data.entry.id}/${r.releaseSeq}`}
                      className="text-decoration-none"
                    >
                      <Badge bg="light" text="dark">#{r.releaseSeq}{r.year != null ? ` · ${r.year}` : ""}</Badge>
                    </Link>
                  ))}
                </div>
              )}
            </Card.Body>
          </Card>
        </Col>

        <Col lg={8}>
          <Card className="shadow-sm mb-3">
            <Card.Body>
              <Card.Title>Places (Magazines)</Card.Title>
              {magazineGroups.length === 0 && <div className="text-secondary">No magazine references</div>}
              {magazineGroups.length > 0 && (
                <div className="d-flex flex-column gap-3">
                  {magazineGroups.map((group) => (
                    <div key={group.magazineId ?? "unknown"}>
                      <div className="d-flex align-items-center justify-content-between">
                        <div className="fw-semibold">
                          {group.magazineId != null ? (
                            <Link href={`/zxdb/magazines/${group.magazineId}`}>
                              {group.magazineName ?? `Magazine #${group.magazineId}`}
                            </Link>
                          ) : (
                            <span className="text-secondary">Unknown magazine</span>
                          )}
                        </div>
                        <div className="text-secondary small">{group.items.length} reference{group.items.length === 1 ? "" : "s"}</div>
                      </div>
                      {groupIssueRefs(group.items).map((issueGroup) => (
                        <div key={issueGroup.issueId} className="mt-2">
                          <div className="d-flex align-items-center justify-content-between">
                            <div>
                              <Link href={`/zxdb/issues/${issueGroup.issueId}`}>Issue #{issueGroup.issueId}</Link>
                              <div className="text-secondary small">{formatIssue(issueGroup.issue) || "-"}</div>
                            </div>
                            <div className="text-secondary small">
                              {issueGroup.items.length} reference{issueGroup.items.length === 1 ? "" : "s"}
                            </div>
                          </div>
                          <Table size="sm" striped className="align-middle mt-2">
                              <thead>
                                <tr>
                                  <th style={{ width: 80 }}>Page</th>
                                  <th style={{ width: 120 }}>Type</th>
                                  <th style={{ width: 100 }}>Original</th>
                                  <th>Notes</th>
                                </tr>
                              </thead>
                              <tbody>
                                {issueGroup.items.map((m) => (
                                  <tr key={m.id}>
                                    <td>{m.page}</td>
                                    <td>{m.referencetypeName ?? `#${m.referencetypeId}`}</td>
                                    <td>{m.isOriginal ? "Yes" : "No"}</td>
                                    <td>{m.scoreGroup || "-"}</td>
                                  </tr>
                                ))}
                              </tbody>
                          </Table>
                        </div>
                      ))}
                    </div>
                  ))}
                </div>
              )}
            </Card.Body>
          </Card>

          <Card className="shadow-sm mb-3">
            <Card.Body>
              <Card.Title>Downloads</Card.Title>
              {groupedDownloads.length === 0 && <div className="text-secondary">No downloads</div>}
              {groupedDownloads.map(([type, items]) => (
                <div key={type} className="mb-4">
                  <h6 className="text-primary border-bottom pb-1 mb-2">{type}</h6>
                  <Table size="sm" striped className="align-middle">
                      <thead>
                        <tr>
                          <th>Link</th>
                          <th style={{ width: 100 }} className="text-end">Size</th>
                          <th style={{ width: 180 }}>MD5</th>
                          <th>Flags</th>
                          <th>Details</th>
                          <th>Comments</th>
                        </tr>
                      </thead>
                      <tbody>
                        {items?.map((d) => {
                          const isHttp = d.link.startsWith("http://") || d.link.startsWith("https://");
                          const fileName = d.link.split("/").pop() || "file";
                          const canPreview = d.localLink && fileName.toLowerCase().match(/\.(txt|nfo|png|jpg|jpeg|gif|pdf)$/);
                          return (
                            <tr key={d.id}>
                              <td>
                                <div className="d-flex flex-column gap-1">
                                  <div className="d-flex align-items-center gap-2">
                                    {isHttp ? (
                                      <a href={d.link} target="_blank" rel="noopener noreferrer" className="text-break small">{d.link}</a>
                                    ) : (
                                      <span className="text-break small">{d.link}</span>
                                    )}
                                    {canPreview && (
                                      <button
                                        className="btn btn-xs btn-outline-info py-0 px-1"
                                        style={{ fontSize: "0.6rem" }}
                                        onClick={() => setViewer({ url: d.localLink!, title: fileName })}
                                      >
                                        Preview
                                      </button>
                                    )}
                                  </div>
                                  {d.localLink && (
                                    <a href={d.localLink} className="btn btn-xs btn-success py-0 px-1" style={{ fontSize: "0.7rem", width: "fit-content" }}>
                                      Local Mirror
                                    </a>
                                  )}
                                </div>
                              </td>
                              <td className="text-end">{typeof d.size === "number" ? d.size.toLocaleString() : "-"}</td>
                              <td><code style={{ fontSize: "0.75rem" }}>{d.md5 ?? "-"}</code></td>
                              <td>
                                <div className="d-flex gap-1 flex-wrap">
                                  {d.isDemo ? <span className="badge text-bg-warning">Demo</span> : null}
                                  {d.scheme.name ? <span className="badge text-bg-info">{d.scheme.name}</span> : null}
                                  {d.source.name ? <span className="badge text-bg-light border">{d.source.name}</span> : null}
                                  {d.case.name ? <span className="badge text-bg-secondary">{d.case.name}</span> : null}
                                </div>
                              </td>
                              <td>
                                <div className="d-flex gap-2 flex-wrap align-items-center">
                                  {d.language.name ? (
                                    <Link className="badge text-bg-info text-decoration-none" href={`/zxdb/languages/${d.language.id}`}>{d.language.name}</Link>
                                  ) : null}
                                  {d.machinetype.name ? (
                                    <Link className="badge text-bg-primary text-decoration-none" href={`/zxdb/machinetypes/${d.machinetype.id}`}>{d.machinetype.name}</Link>
                                  ) : null}
                                  {typeof d.year === "number" ? <span className="badge text-bg-dark">{d.year}</span> : null}
                                </div>
                              </td>
                              <td className="small">{d.comments ?? ""}</td>
                            </tr>
                          );
                        })}
                      </tbody>
                  </Table>
                </div>
              ))}
            </Card.Body>
          </Card>

          <Card className="shadow-sm mb-3">
            <Card.Body>
              <Card.Title>Scraps / Media</Card.Title>
              {groupedScraps.length === 0 && <div className="text-secondary">No scraps</div>}
              {groupedScraps.map(([type, items]) => (
                <div key={type} className="mb-4">
                  <h6 className="text-primary border-bottom pb-1 mb-2">{type}</h6>
                  <Table size="sm" striped className="align-middle">
                      <thead>
                        <tr>
                          <th>Link</th>
                          <th style={{ width: 100 }} className="text-end">Size</th>
                          <th>Flags</th>
                          <th>Details</th>
                          <th>Rationale</th>
                        </tr>
                      </thead>
                      <tbody>
                        {items?.map((s) => {
                          const isHttp = s.link?.startsWith("http://") || s.link?.startsWith("https://");
                          const fileName = s.link?.split("/").pop() || "file";
                          const canPreview = s.localLink && fileName.toLowerCase().match(/\.(txt|nfo|png|jpg|jpeg|gif|pdf)$/);
                          return (
                            <tr key={s.id}>
                              <td>
                                <div className="d-flex flex-column gap-1">
                                  <div className="d-flex align-items-center gap-2">
                                    {s.link ? (
                                      isHttp ? (
                                        <a href={s.link} target="_blank" rel="noopener noreferrer" className="text-break small">{s.link}</a>
                                      ) : (
                                        <span className="text-break small">{s.link}</span>
                                      )
                                    ) : (
                                      <span className="text-secondary">-</span>
                                    )}
                                    {canPreview && (
                                      <button
                                        className="btn btn-xs btn-outline-info py-0 px-1"
                                        style={{ fontSize: "0.6rem" }}
                                        onClick={() => setViewer({ url: s.localLink!, title: fileName })}
                                      >
                                        Preview
                                      </button>
                                    )}
                                  </div>
                                  {s.localLink && (
                                    <a href={s.localLink} className="btn btn-xs btn-success py-0 px-1" style={{ fontSize: "0.7rem", width: "fit-content" }}>
                                      Local Mirror
                                    </a>
                                  )}
                                </div>
                              </td>
                              <td className="text-end">{typeof s.size === "number" ? s.size.toLocaleString() : "-"}</td>
                              <td>
                                <div className="d-flex gap-1 flex-wrap">
                                  {s.isDemo ? <span className="badge text-bg-warning">Demo</span> : null}
                                  {s.scheme.name ? <span className="badge text-bg-info">{s.scheme.name}</span> : null}
                                  {s.source.name ? <span className="badge text-bg-light border">{s.source.name}</span> : null}
                                  {s.case.name ? <span className="badge text-bg-secondary">{s.case.name}</span> : null}
                                </div>
                              </td>
                              <td>
                                <div className="d-flex gap-2 flex-wrap align-items-center">
                                  {s.language.name ? (
                                    <Link className="badge text-bg-info text-decoration-none" href={`/zxdb/languages/${s.language.id}`}>{s.language.name}</Link>
                                  ) : null}
                                  {s.machinetype.name ? (
                                    <Link className="badge text-bg-primary text-decoration-none" href={`/zxdb/machinetypes/${s.machinetype.id}`}>{s.machinetype.name}</Link>
                                  ) : null}
                                  {typeof s.year === "number" ? <span className="badge text-bg-dark">{s.year}</span> : null}
                                </div>
                              </td>
                              <td className="small">{s.rationale}</td>
                            </tr>
                          );
                        })}
                      </tbody>
                  </Table>
                </div>
              ))}
            </Card.Body>
          </Card>

          <Card className="shadow-sm mb-3">
            <Card.Body>
              <Card.Title>Issue Files</Card.Title>
              {data.files.length === 0 && <div className="text-secondary">No files linked</div>}
              {data.files.length > 0 && (
                <Table size="sm" striped className="align-middle">
                  <thead>
                    <tr>
                      <th>Type</th>
                      <th>Link</th>
                      <th style={{ width: 120 }} className="text-end">Size</th>
                      <th style={{ width: 240 }}>MD5</th>
                      <th>Comments</th>
                    </tr>
                  </thead>
                  <tbody>
                    {data.files.map((f) => {
                      const isHttp = f.link.startsWith("http://") || f.link.startsWith("https://");
                      return (
                        <tr key={f.id}>
                          <td><Badge bg="secondary">{f.type.name}</Badge></td>
                          <td>
                            {isHttp ? (
                              <a href={f.link} target="_blank" rel="noopener noreferrer">{f.link}</a>
                            ) : (
                              <span>{f.link}</span>
                            )}
                          </td>
                          <td className="text-end">{f.size != null ? new Intl.NumberFormat().format(f.size) : "-"}</td>
                          <td><code>{f.md5 ?? "-"}</code></td>
                          <td>{f.comments ?? ""}</td>
                        </tr>
                      );
                    })}
                  </tbody>
                </Table>
              )}
            </Card.Body>
          </Card>
        </Col>
      </Row>

      <div className="d-flex align-items-center gap-2">
        <Link className="btn btn-sm btn-outline-secondary" href={`/zxdb/releases/${data.entry.id}/${data.release.releaseSeq}`}>Permalink</Link>
        <Link className="btn btn-sm btn-outline-primary" href="/zxdb/releases">Back to Releases</Link>
      </div>
      {viewer && (
        <FileViewer
          url={viewer.url}
          title={viewer.title}
          onClose={() => setViewer(null)}
        />
      )}
    </div>
  );
}
