import { useMutation, useQuery } from "@tanstack/react-query";
import type { AxiosError } from "axios";
import {
  Download,
  FileSpreadsheet,
  Pencil,
  Plus,
  RefreshCw,
  Search,
  Trash2,
  Upload,
} from "lucide-react";
import * as React from "react";
import { Link, useNavigate } from "react-router-dom";
import { RoleGuard } from "../../../components/auth/RoleGuard";
import { Badge } from "../../../components/ui/badge";
import { Button } from "../../../components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "../../../components/ui/card";
import { Checkbox } from "../../../components/ui/checkbox";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "../../../components/ui/dialog";
import { Input } from "../../../components/ui/input";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "../../../components/ui/table";
import {
  type TenantSummary,
  deleteTenant,
  deleteTenantsBulk,
  exportTenantsCSV,
  fetchMe,
  fetchTenants,
  importTenantsCSV,
} from "../../../lib/adminApi";
import { t } from "../../../lib/i18n";
import {
  type TenantImportPreviewRow,
  buildTenantImportPreview,
  parseTenantCSV,
  serializeTenantImportCSV,
} from "../utils/tenantCsvImport";

const tenantCSVTemplate =
  "tenant_id,name,type,parent_tenant_id,slug,memo,email_domain\n";

function TenantListPage() {
  const navigate = useNavigate();
  const [selectedIds, setSelectedIds] = React.useState<string[]>([]);
  const [search, setSearch] = React.useState("");
  const fileInputRef = React.useRef<HTMLInputElement | null>(null);
  const [importMessage, setImportMessage] = React.useState("");
  const [previewRows, setPreviewRows] = React.useState<
    TenantImportPreviewRow[]
  >([]);
  const [selectedMatches, setSelectedMatches] = React.useState<
    Record<number, string>
  >({});
  const [previewOpen, setPreviewOpen] = React.useState(false);

  const { data: profile } = useQuery({
    queryKey: ["me"],
    queryFn: fetchMe,
  });

  // Redirect tenant_admin ONLY if they have one or fewer manageable tenants in the list
  React.useEffect(() => {
    if (profile?.role === "tenant_admin") {
      const manageableCount = profile.manageableTenants?.length ?? 0;
      if (
        (manageableCount === 1 || manageableCount === 0) &&
        profile.tenantId
      ) {
        navigate(`/tenants/${profile.tenantId}`, { replace: true });
      }
    }
  }, [profile, navigate]);

  const query = useQuery({
    queryKey: ["tenants", { limit: 1000, offset: 0 }],
    queryFn: () => fetchTenants(1000, 0),
    enabled:
      profile?.role === "super_admin" ||
      (profile?.role === "tenant_admin" &&
        (profile.manageableTenants?.length ?? 0) > 1),
  });

  const deleteMutation = useMutation({
    mutationFn: (tenantId: string) => deleteTenant(tenantId),
    onSuccess: () => {
      query.refetch();
    },
  });

  const deleteBulkMutation = useMutation({
    mutationFn: (ids: string[]) => deleteTenantsBulk(ids),
    onSuccess: () => {
      setSelectedIds([]);
      query.refetch();
    },
  });

  const exportMutation = useMutation({
    mutationFn: exportTenantsCSV,
    onSuccess: ({ blob, filename }) => {
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = filename;
      document.body.appendChild(link);
      link.click();
      link.remove();
      window.URL.revokeObjectURL(url);
    },
  });

  const importMutation = useMutation({
    mutationFn: (file: File) => importTenantsCSV(file),
    onSuccess: (result) => {
      setImportMessage(
        t(
          "msg.admin.tenants.import_result",
          "생성 {{created}}, 갱신 {{updated}}, 실패 {{failed}}",
          {
            created: result.created,
            updated: result.updated,
            failed: result.failed,
          },
        ),
      );
      setPreviewOpen(false);
      setPreviewRows([]);
      setSelectedMatches({});
      query.refetch();
    },
    onError: (error: AxiosError<{ error?: string }>) => {
      setImportMessage(
        error.response?.data?.error ??
          t(
            "msg.admin.tenants.import_error",
            "테넌트 가져오기에 실패했습니다.",
          ),
      );
    },
  });

  if (
    profile &&
    profile.role !== "super_admin" &&
    profile.role !== "tenant_admin"
  ) {
    return (
      <div className="flex h-[50vh] flex-col items-center justify-center space-y-4">
        <h3 className="text-xl font-bold">
          {t("msg.admin.common.forbidden", "접근 권한이 없습니다.")}
        </h3>
        <Button onClick={() => navigate("/")}>
          {t("ui.common.go_home", "홈으로 이동")}
        </Button>
      </div>
    );
  }

  if (
    profile?.role === "tenant_admin" &&
    (profile.manageableTenants?.length ?? 0) <= 1
  ) {
    return null;
  }

  const errorMsg = (query.error as AxiosError<{ error?: string }>)?.response
    ?.data?.error;
  const fallbackError =
    !errorMsg && query.isError
      ? t("msg.admin.tenants.fetch_error", "테넌트 목록 조회에 실패했습니다.")
      : null;

  const allTenants = query.data?.items ?? [];
  const tenants = React.useMemo(() => {
    if (!search.trim()) return allTenants;
    const term = search.toLowerCase();
    return allTenants.filter(
      (t) =>
        t.name.toLowerCase().includes(term) ||
        t.slug.toLowerCase().includes(term),
    );
  }, [allTenants, search]);

  const handleSelectAll = (checked: boolean) => {
    if (checked) {
      setSelectedIds(tenants.map((t) => t.id));
    } else {
      setSelectedIds([]);
    }
  };

  const handleSelect = (id: string, checked: boolean) => {
    if (checked) {
      setSelectedIds((prev) => [...prev, id]);
    } else {
      setSelectedIds((prev) => prev.filter((i) => i !== id));
    }
  };

  const handleDeleteBulk = () => {
    if (selectedIds.length === 0) return;
    if (
      !window.confirm(
        t(
          "msg.admin.tenants.delete_bulk_confirm",
          "선택한 {{count}}개 테넌트를 삭제할까요?",
          { count: selectedIds.length },
        ),
      )
    ) {
      return;
    }
    deleteBulkMutation.mutate(selectedIds);
  };

  const handleTemplateDownload = () => {
    const blob = new Blob([tenantCSVTemplate], { type: "text/csv" });
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = "tenant-import-template.csv";
    document.body.appendChild(link);
    link.click();
    link.remove();
    window.URL.revokeObjectURL(url);
  };

  const handleImportFile = async (
    event: React.ChangeEvent<HTMLInputElement>,
  ) => {
    const file = event.target.files?.[0];
    event.target.value = "";
    if (!file) return;
    setImportMessage("");
    const text = await file.text();
    const rows = parseTenantCSV(text);
    if (rows.length === 0) {
      setImportMessage(
        t("msg.admin.tenants.import_empty", "가져올 테넌트 행이 없습니다."),
      );
      return;
    }
    const preview = buildTenantImportPreview(rows, allTenants);
    setPreviewRows(preview);
    setSelectedMatches(
      Object.fromEntries(
        preview
          .filter((row) => row.defaultTenantId)
          .map((row) => [row.row.rowNumber, row.defaultTenantId]),
      ),
    );
    setPreviewOpen(true);
  };

  const handleImportConfirm = () => {
    const csv = serializeTenantImportCSV(previewRows, selectedMatches);
    const file = new File([csv], "tenants.csv", { type: "text/csv" });
    importMutation.mutate(file);
  };

  const handleDelete = (tenantId: string, tenantName: string) => {
    if (
      !window.confirm(
        t(
          "msg.admin.tenants.delete_confirm",
          '테넌트 "{{name}}"를 삭제할까요?',
          { name: tenantName },
        ),
      )
    ) {
      return;
    }
    deleteMutation.mutate(tenantId);
  };

  return (
    <div className="space-y-6 flex flex-col h-[calc(100vh-theme(spacing.32))]">
      <header className="flex flex-wrap items-start justify-between gap-4 flex-shrink-0 sticky top-[-2.5rem] z-20 bg-background/95 backdrop-blur pt-4 pb-2 -mt-4">
        <div className="space-y-2">
          <h2 className="text-3xl font-semibold">
            {t("ui.admin.tenants.title", "테넌트 목록")}
          </h2>
          <p className="text-sm text-[var(--color-muted)]">
            {t(
              "msg.admin.tenants.subtitle",
              "시스템에 등록된 모든 테넌트를 평면 목록으로 확인하고 관리합니다.",
            )}
          </p>
        </div>
        <div className="flex items-center gap-2">
          <RoleGuard roles={["super_admin"]}>
            {selectedIds.length > 0 && (
              <Button
                variant="destructive"
                onClick={handleDeleteBulk}
                disabled={deleteBulkMutation.isPending}
                className="gap-2"
              >
                <Trash2 size={16} />
                {t("ui.admin.tenants.delete_selected", "선택 삭제")} (
                {selectedIds.length})
              </Button>
            )}
          </RoleGuard>

          <RoleGuard roles={["super_admin"]}>
            <input
              ref={fileInputRef}
              type="file"
              accept=".csv,text/csv"
              className="hidden"
              data-testid="tenant-import-input"
              onChange={handleImportFile}
            />
            <Button
              variant="outline"
              onClick={handleTemplateDownload}
              data-testid="tenant-template-btn"
            >
              <FileSpreadsheet size={16} />
              {t("ui.admin.tenants.csv_template", "템플릿")}
            </Button>
            <Button
              variant="outline"
              onClick={() => exportMutation.mutate()}
              disabled={exportMutation.isPending}
              data-testid="tenant-export-btn"
            >
              <Download size={16} />
              {t("ui.admin.tenants.export", "내보내기")}
            </Button>
            <Button
              variant="outline"
              onClick={() => fileInputRef.current?.click()}
              disabled={importMutation.isPending}
              data-testid="tenant-import-btn"
            >
              <Upload size={16} />
              {t("ui.admin.tenants.import", "가져오기")}
            </Button>
          </RoleGuard>

          <Button
            variant="outline"
            onClick={() => query.refetch()}
            disabled={query.isFetching}
          >
            <RefreshCw size={16} />
            {t("ui.common.refresh", "새로고침")}
          </Button>
          <RoleGuard roles={["super_admin"]}>
            <Button asChild>
              <Link to="/tenants/new">
                <Plus size={16} />
                {t("ui.admin.tenants.add", "테넌트 추가")}
              </Link>
            </Button>
          </RoleGuard>
        </div>
        {importMessage && (
          <div
            className="basis-full rounded-md border border-border bg-secondary px-3 py-2 text-sm"
            data-testid="tenant-import-result"
          >
            {importMessage}
          </div>
        )}
      </header>

      <Card className="bg-[var(--color-panel)] flex-1 flex flex-col min-h-0 overflow-hidden">
        <CardHeader className="flex flex-row items-center justify-between flex-shrink-0">
          <div>
            <CardTitle>
              {t("ui.admin.tenants.registry.title", "Tenant Registry")}
            </CardTitle>
            <CardDescription>
              {t("msg.admin.tenants.registry.count", "총 {{count}}개 테넌트", {
                count: query.data?.total ?? 0,
              })}
            </CardDescription>
          </div>
        </CardHeader>
        <CardContent className="flex-1 flex flex-col min-h-0 pt-0">
          <div className="mb-6 flex items-center gap-4 flex-shrink-0">
            <div className="relative flex-1 min-w-[240px] max-w-sm">
              <Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
              <Input
                placeholder={t(
                  "ui.admin.tenants.list.search_placeholder",
                  "테넌트 이름 또는 슬러그 검색...",
                )}
                className="pl-9"
                value={search}
                onChange={(e) => setSearch(e.target.value)}
              />
            </div>
          </div>

          {(errorMsg || fallbackError) && (
            <div className="mb-4 rounded-lg border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive flex-shrink-0">
              {errorMsg ?? fallbackError}
            </div>
          )}

          <div className="flex-1 rounded-md border overflow-hidden flex flex-col">
            <div className="flex-1 overflow-auto relative custom-scrollbar">
              <Table>
                <TableHeader className="sticky top-0 z-10 bg-secondary shadow-sm">
                  <TableRow>
                    <TableHead className="w-[40px]">
                      <Checkbox
                        checked={
                          tenants.length > 0 &&
                          selectedIds.length === tenants.length
                        }
                        onCheckedChange={(checked) =>
                          handleSelectAll(!!checked)
                        }
                      />
                    </TableHead>
                    <TableHead className="min-w-[220px]">
                      {t("ui.admin.tenants.table.id", "ID")}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.tenants.table.name", "NAME")}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.tenants.table.type", "TYPE")}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.tenants.table.slug", "SLUG")}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.tenants.table.status", "STATUS")}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.tenants.table.members", "MEMBERS")}
                    </TableHead>
                    <TableHead>
                      {t("ui.admin.tenants.table.updated", "UPDATED")}
                    </TableHead>
                    <TableHead className="text-right">
                      {t("ui.admin.tenants.table.actions", "ACTIONS")}
                    </TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {query.isLoading && (
                    <TableRow>
                      <TableCell colSpan={9}>
                        {t("msg.common.loading", "로딩 중...")}
                      </TableCell>
                    </TableRow>
                  )}
                  {!query.isLoading && tenants.length === 0 && (
                    <TableRow>
                      <TableCell
                        colSpan={9}
                        className="text-center py-8 text-muted-foreground"
                      >
                        {t(
                          "msg.admin.tenants.empty",
                          "아직 등록된 테넌트가 없습니다.",
                        )}
                      </TableCell>
                    </TableRow>
                  )}
                  {tenants.map((tenant) => (
                    <TableRow key={tenant.id}>
                      <TableCell>
                        <Checkbox
                          checked={selectedIds.includes(tenant.id)}
                          onCheckedChange={(checked) =>
                            handleSelect(tenant.id, !!checked)
                          }
                        />
                      </TableCell>
                      <TableCell
                        className="max-w-[260px] break-all font-mono text-xs text-muted-foreground"
                        data-testid={`tenant-internal-id-${tenant.id}`}
                      >
                        {tenant.id}
                      </TableCell>
                      <TableCell className="font-semibold">
                        {tenant.name}
                      </TableCell>
                      <TableCell>
                        <Badge
                          variant="outline"
                          className="text-[10px] font-mono"
                        >
                          {t(
                            `domain.tenant_type.${tenant.type?.toLowerCase()}`,
                            tenant.type,
                          )}
                        </Badge>
                      </TableCell>
                      <TableCell className="font-mono text-xs">
                        {tenant.slug}
                      </TableCell>
                      <TableCell>
                        <Badge
                          variant={
                            tenant.status === "active"
                              ? "default"
                              : tenant.status === "pending"
                                ? "secondary"
                                : "muted"
                          }
                        >
                          {t(
                            `ui.common.status.${tenant.status}`,
                            tenant.status,
                          )}
                        </Badge>
                      </TableCell>
                      <TableCell className="font-medium">
                        {tenant.memberCount}
                      </TableCell>
                      <TableCell className="text-xs">
                        {tenant.updatedAt
                          ? new Date(tenant.updatedAt).toLocaleString("ko-KR")
                          : "-"}
                      </TableCell>
                      <TableCell className="text-right">
                        <div className="flex justify-end gap-2">
                          <Button
                            variant="outline"
                            size="sm"
                            onClick={() => navigate(`/tenants/${tenant.id}`)}
                          >
                            <Pencil size={14} />
                            {t("ui.common.edit", "편집")}
                          </Button>
                          <Button
                            variant="outline"
                            size="sm"
                            onClick={() => handleDelete(tenant.id, tenant.name)}
                            disabled={deleteMutation.isPending}
                          >
                            <Trash2 size={14} />
                            {t("ui.common.delete", "삭제")}
                          </Button>
                        </div>
                      </TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </div>
          </div>
        </CardContent>
      </Card>

      <Dialog open={previewOpen} onOpenChange={setPreviewOpen}>
        <DialogContent className="max-w-5xl">
          <DialogHeader>
            <DialogTitle>
              {t("ui.admin.tenants.import_preview.title", "CSV 가져오기 확인")}
            </DialogTitle>
            <DialogDescription>
              {t(
                "msg.admin.tenants.import_preview.description",
                "tenant_id가 없는 행은 기존 테넌트 후보와 비교한 뒤 신규 생성 또는 기존 테넌트 갱신으로 처리합니다.",
              )}
            </DialogDescription>
          </DialogHeader>

          <div className="max-h-[60vh] overflow-auto rounded-md border">
            <Table>
              <TableHeader className="sticky top-0 bg-secondary">
                <TableRow>
                  <TableHead className="w-[72px]">
                    {t("ui.common.row", "행")}
                  </TableHead>
                  <TableHead>
                    {t("ui.admin.tenants.table.name", "NAME")}
                  </TableHead>
                  <TableHead>
                    {t("ui.admin.tenants.table.slug", "SLUG")}
                  </TableHead>
                  <TableHead>
                    {t("ui.admin.tenants.import_preview.match", "매칭")}
                  </TableHead>
                  <TableHead>
                    {t("ui.admin.tenants.import_preview.candidates", "후보")}
                  </TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {previewRows.map((preview) => (
                  <TableRow
                    key={preview.row.rowNumber}
                    data-testid={`tenant-import-preview-row-${preview.row.rowNumber}`}
                  >
                    <TableCell className="font-mono text-xs">
                      {preview.row.rowNumber}
                    </TableCell>
                    <TableCell className="font-medium">
                      {preview.row.name}
                    </TableCell>
                    <TableCell className="font-mono text-xs">
                      {preview.row.slug}
                    </TableCell>
                    <TableCell>
                      {preview.row.tenantId ? (
                        <Badge variant="outline">
                          {t(
                            "ui.admin.tenants.import_preview.fixed_id",
                            "ID 지정됨",
                          )}
                        </Badge>
                      ) : (
                        <select
                          className="h-9 w-full rounded-md border border-input bg-background px-3 text-sm"
                          value={selectedMatches[preview.row.rowNumber] ?? ""}
                          data-testid={`tenant-import-match-select-${preview.row.rowNumber}`}
                          onChange={(event) =>
                            setSelectedMatches((prev) => ({
                              ...prev,
                              [preview.row.rowNumber]: event.target.value,
                            }))
                          }
                        >
                          <option value="">
                            {t(
                              "ui.admin.tenants.import_preview.create_new",
                              "신규 생성",
                            )}
                          </option>
                          {preview.candidates.map((candidate) => (
                            <option
                              key={candidate.tenantId}
                              value={candidate.tenantId}
                            >
                              {candidate.name} ({candidate.slug})
                            </option>
                          ))}
                        </select>
                      )}
                    </TableCell>
                    <TableCell>
                      {preview.candidates.length > 0 ? (
                        <div className="flex flex-wrap gap-1">
                          {preview.candidates.map((candidate) => (
                            <Badge
                              key={candidate.tenantId}
                              variant={
                                candidate.score >= 0.95 ? "default" : "outline"
                              }
                              data-testid="tenant-import-candidate"
                            >
                              {candidate.name}{" "}
                              {Math.round(candidate.score * 100)}%
                            </Badge>
                          ))}
                        </div>
                      ) : (
                        <span className="text-sm text-muted-foreground">
                          {t(
                            "ui.admin.tenants.import_preview.no_candidates",
                            "후보 없음",
                          )}
                        </span>
                      )}
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </div>

          <DialogFooter>
            <Button variant="outline" onClick={() => setPreviewOpen(false)}>
              {t("ui.common.cancel", "취소")}
            </Button>
            <Button
              onClick={handleImportConfirm}
              disabled={importMutation.isPending}
              data-testid="tenant-import-confirm-btn"
            >
              {t("ui.admin.tenants.import_preview.confirm", "가져오기 실행")}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

export default TenantListPage;
