import { useEffect, useMemo, useState } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { ArrowUpDown, Loader2 } from "lucide-react";
import { apiClient } from "@/shared/api/client";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import SearchableSelect, { type SearchableOption } from "@/components/council/SearchableSelect";
import { DEPARTMENT_OPTIONS, GROUP_OPTIONS, STATUS_OPTIONS, ALL_OPTION_VALUE } from "@/components/council/SelectOptions";
import type { ApplicationItem, ApplicationStatus } from "@/data/mockApplications";
import { EvidenceFilesTableCell } from "@/components/evidence/EvidenceFilesTableCell";
import { MOCK_APPLICATIONS } from "@/data/mockApplications";
import { DOCX_DEMO_APPLICATION } from "@/components/council/demoApplicationInstances";
import ApplicationIdeaRow from "@/components/council/ApplicationIdeaRow";
import { useVisibilityAwareRefetchInterval } from "@/hooks/useVisibilityAwareRefetchInterval";
import { POLL_INTERVALS } from "@/shared/config/polling";
import { buildCouncilApplicationReviewHref } from "@/lib/applicationReviewNavigation";
import { formatIsoToDdMmYyyy, formatIsoToDdMmYyyyHhMm } from "@/lib/vnDateFormat";

type SortOrder = "asc" | "desc";

interface ApplicationResponse {
  data: ApplicationItem[];
  pagination: { page: number; pageSize: number; totalItems: number; totalPages: number };
}

interface ApplicationReportFile {
  fileName: string;
  publicUrl: string;
  sizeBytes: number;
  updatedAt: string;
}

interface FilterState {
  name: string;
  subjectId: string;
  conferenceId: string;
  status: string;
  dateFrom: string;
  dateTo: string;
  authorName: string;
  reviewerName: string;
  supervisorId: string;
  reviewStatus: string;
  topicTypeId: string;
  boardId: string;
  sortBy: string;
  sortOrder: SortOrder;
  page: number;
  pageSize: number;
}

const DEFAULT_FILTERS: FilterState = {
  name: "",
  subjectId: "",
  conferenceId: "",
  status: "",
  dateFrom: "",
  dateTo: "",
  authorName: "",
  reviewerName: "",
  supervisorId: "",
  reviewStatus: "",
  topicTypeId: "",
  boardId: "",
  sortBy: "submittedDate",
  sortOrder: "desc",
  page: 1,
  pageSize: 20,
};

/** Filter stores YYYY-MM-DD (API); UI shows dd/MM/yyyy */
function isoDateToDdMmYyyy(iso: string) {
  if (!iso || !/^\d{4}-\d{2}-\d{2}$/.test(iso)) return "";
  const [y, m, d] = iso.split("-");
  return `${d}/${m}/${y}`;
}

function parseDdMmYyyyToIso(s: string): string {
  const trimmed = s.trim();
  if (!trimmed) return "";
  const match = trimmed.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
  if (!match) return "";
  const dd = Number(match[1]);
  const mm = Number(match[2]);
  const yyyy = Number(match[3]);
  if (mm < 1 || mm > 12 || dd < 1 || dd > 31) return "";
  const dt = new Date(yyyy, mm - 1, dd);
  if (dt.getFullYear() !== yyyy || dt.getMonth() !== mm - 1 || dt.getDate() !== dd) return "";
  return `${yyyy}-${String(mm).padStart(2, "0")}-${String(dd).padStart(2, "0")}`;
}

function formatDate(iso: string | null | undefined, withTime = false) {
  if (!iso) return "";
  if (withTime) return formatIsoToDdMmYyyyHhMm(iso);
  return formatIsoToDdMmYyyy(iso);
}

function optionLabel(options: ReadonlyArray<{ value: string; label: string }>, value?: string | null) {
  if (value == null || value === "") return "";
  return options.find((o) => o.value === value)?.label ?? "";
}

function statusBadge(status: ApplicationStatus) {
  const label = optionLabel(STATUS_OPTIONS, status) || String(status);
  switch (status) {
    case "pending":
      return <Badge className="bg-amber-500 hover:bg-amber-500/90">{label}</Badge>;
    case "approved":
      return <Badge className="bg-green-600 hover:bg-green-600/90">{label}</Badge>;
    case "rejected":
      return <Badge variant="destructive">{label}</Badge>;
    case "transferred":
      return <Badge className="bg-blue-600 hover:bg-blue-600/90">{label}</Badge>;
    case "under_review":
      return <Badge variant="secondary">{label}</Badge>;
    case "reviewed":
      return <Badge variant="outline" className="border-green-500 text-green-700">{label}</Badge>;
    default:
      return <Badge variant="secondary">-</Badge>;
  }
}

function parseFilters(params: URLSearchParams): FilterState {
  return {
    ...DEFAULT_FILTERS,
    name: params.get("name") ?? "",
    subjectId: params.get("subjectId") ?? "",
    conferenceId: params.get("conferenceId") ?? "",
    status: params.get("status") ?? "",
    dateFrom: params.get("dateFrom") ?? "",
    dateTo: params.get("dateTo") ?? "",
    authorName: params.get("authorName") ?? "",
    reviewerName: params.get("reviewerName") ?? "",
    supervisorId: params.get("supervisorId") ?? "",
    reviewStatus: params.get("reviewStatus") ?? "",
    topicTypeId: params.get("topicTypeId") ?? "",
    boardId: params.get("boardId") ?? "",
    sortBy: params.get("sortBy") ?? DEFAULT_FILTERS.sortBy,
    sortOrder: (params.get("sortOrder") as SortOrder) || DEFAULT_FILTERS.sortOrder,
    page: Number(params.get("page") ?? DEFAULT_FILTERS.page),
    pageSize: Number(params.get("pageSize") ?? DEFAULT_FILTERS.pageSize),
  };
}

function toSearchParams(filters: FilterState) {
  const params = new URLSearchParams();
  Object.entries(filters).forEach(([key, value]) => {
    const normalized = String(value ?? "");
    const defaultValue = String((DEFAULT_FILTERS as any)[key] ?? "");
    if (normalized && normalized !== defaultValue) {
      params.set(key, normalized);
    }
  });
  return params;
}

function toOptionList(input: unknown): SearchableOption[] {
  if (!Array.isArray(input)) return [];
  return input
    .map((item: any) => {
      const value = String(item?.id ?? item?.value ?? "");
      const label = String(item?.name ?? item?.fullName ?? item?.label ?? "");
      if (!value || !label) return null;
      return { value, label };
    })
    .filter(Boolean) as SearchableOption[];
}

function getNestedData<T = unknown>(raw: any): T {
  if (Array.isArray(raw)) return raw as T;
  if (raw?.data) return raw.data as T;
  return raw as T;
}

function useLookupQuery(path: string) {
  return useQuery({
    queryKey: ["dashboard-lookup", path],
    queryFn: async () => {
      const data = await apiClient.get(path);
      return toOptionList(getNestedData(data));
    },
    staleTime: 5 * 60 * 1000,
  });
}

export default function ApprovedApplicationsList() {
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const [searchParams, setSearchParams] = useSearchParams();
  const [filters, setFilters] = useState<FilterState>(() => parseFilters(searchParams));
  const [nameInput, setNameInput] = useState(filters.name);
  const [authorInput, setAuthorInput] = useState(filters.authorName);
  const [reviewerInput, setReviewerInput] = useState(filters.reviewerName);
  const [dateFromText, setDateFromText] = useState(() => isoDateToDdMmYyyy(filters.dateFrom));
  const [statusOverrides, setStatusOverrides] = useState<Record<string, ApplicationStatus>>({});
  const [isExportingExcel, setIsExportingExcel] = useState(false);

  useEffect(() => {
    const handle = setTimeout(() => {
      setFilters((prev) => ({ ...prev, name: nameInput, page: 1 }));
    }, 300);
    return () => clearTimeout(handle);
  }, [nameInput]);

  useEffect(() => {
    const handle = setTimeout(() => {
      setFilters((prev) => ({ ...prev, authorName: authorInput, page: 1 }));
    }, 300);
    return () => clearTimeout(handle);
  }, [authorInput]);

  useEffect(() => {
    const handle = setTimeout(() => {
      setFilters((prev) => ({ ...prev, reviewerName: reviewerInput, page: 1 }));
    }, 300);
    return () => clearTimeout(handle);
  }, [reviewerInput]);

  useEffect(() => {
    setDateFromText(isoDateToDdMmYyyy(filters.dateFrom));
  }, [filters.dateFrom]);

  useEffect(() => {
    setSearchParams(toSearchParams(filters), { replace: true });
  }, [filters, setSearchParams]);

  const conferencesQuery = useLookupQuery("/api/conferences");
  const supervisorsQuery = useLookupQuery("/api/supervisors");
  const applicationsSafetyPoll = useVisibilityAwareRefetchInterval(
    POLL_INTERVALS.councilApplicationsSafetyNet,
  );

  const reportSyncQuery = useQuery({
    queryKey: ["application-report-files-sync"],
    queryFn: async () => apiClient.get<{ files: ApplicationReportFile[] }>("/api/v1/application-reports"),
    staleTime: 30_000,
    refetchOnMount: true,
    refetchOnWindowFocus: true,
  });

  const applicationsQuery = useQuery({
    queryKey: ["applications", filters],
    queryFn: async (): Promise<ApplicationResponse> => {
      try {
        return await apiClient.get("/api/applications", { params: filters });
      } catch {
        const filtered = MOCK_APPLICATIONS.filter((item) => {
          const text = filters.name.trim().toLowerCase();
          if (text && !item.name.toLowerCase().includes(text)) return false;
          const authorQ = filters.authorName.trim().toLowerCase();
          if (authorQ && !item.author.name.toLowerCase().includes(authorQ)) return false;
          const reviewerQ = filters.reviewerName.trim().toLowerCase();
          if (reviewerQ && !item.reviewer?.name.toLowerCase().includes(reviewerQ)) return false;
          if (filters.status && item.status !== filters.status) return false;
          if (filters.reviewStatus && item.reviewStatus !== filters.reviewStatus) return false;
          if (filters.dateFrom && new Date(item.submittedDate) < new Date(filters.dateFrom)) return false;
          if (filters.dateTo && new Date(item.submittedDate) > new Date(`${filters.dateTo}T23:59:59`)) return false;
          return true;
        });

        const sorted = [...filtered].sort((a, b) => {
          const order = filters.sortOrder === "asc" ? 1 : -1;
          if (filters.sortBy === "name") return a.name.localeCompare(b.name) * order;
          if (filters.sortBy === "author") return a.author.name.localeCompare(b.author.name) * order;
          if (filters.sortBy === "reviewDeadline") return String(a.reviewDeadline).localeCompare(String(b.reviewDeadline)) * order;
          return (new Date(a.submittedDate).getTime() - new Date(b.submittedDate).getTime()) * order;
        });

        const start = (filters.page - 1) * filters.pageSize;
        const end = start + filters.pageSize;
        const pageData = sorted.slice(start, end);
        return {
          data: pageData,
          pagination: {
            page: filters.page,
            pageSize: filters.pageSize,
            totalItems: filtered.length,
            totalPages: Math.max(1, Math.ceil(filtered.length / filters.pageSize)),
          },
        };
      }
    },
    placeholderData: (previous) => previous,
    staleTime: 30_000,
    refetchInterval: applicationsSafetyPoll,
    refetchOnWindowFocus: true,
    refetchOnReconnect: true,
  });

  useEffect(() => {
    if (!reportSyncQuery.dataUpdatedAt) return;
    void queryClient.invalidateQueries({ queryKey: ["applications"] });
  }, [queryClient, reportSyncQuery.dataUpdatedAt]);

  const dataWithDocxDemo = useMemo(() => {
    const baseData = applicationsQuery.data?.data ?? [];
    const exists = baseData.some((item) => item.id === DOCX_DEMO_APPLICATION.id);
    if (exists) return baseData;
    return [DOCX_DEMO_APPLICATION, ...baseData];
  }, [applicationsQuery.data?.data]);
  const pagination = applicationsQuery.data?.pagination ?? { page: 1, pageSize: filters.pageSize, totalItems: 0, totalPages: 1 };

  const setFilter = (key: keyof FilterState, value: string | number) => {
    setFilters((prev) => ({ ...prev, [key]: value, page: key === "page" || key === "pageSize" ? Number(value) : 1 }));
  };

  const handleReset = () => {
    setNameInput("");
    setAuthorInput("");
    setReviewerInput("");
    setDateFromText("");
    setFilters(DEFAULT_FILTERS);
  };

  const toggleSort = (sortBy: string) => {
    setFilters((prev) => ({
      ...prev,
      sortBy,
      sortOrder: prev.sortBy === sortBy && prev.sortOrder === "desc" ? "asc" : "desc",
      page: 1,
    }));
  };

  const exportExcel = async () => {
    setIsExportingExcel(true);
    try {
      const blobData = await apiClient.get<Blob>("/api/applications/export", {
        params: filters,
        responseType: "blob",
      } as any);
      const blob = new Blob([blobData], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      });
      const url = URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = "applications-export.xlsx";
      link.click();
      URL.revokeObjectURL(url);
    } finally {
      setIsExportingExcel(false);
    }
  };

  const getStatus = (item: ApplicationItem): ApplicationStatus => statusOverrides[item.id] ?? item.status;

  const handleReviewAction = (applicationId: string, nextStatus: ApplicationStatus) => {
    setStatusOverrides((prev) => ({ ...prev, [applicationId]: nextStatus }));
  };

  const handleOpenReview = (applicationId: string) => {
    const currentQuery = searchParams.toString();
    const returnTo = currentQuery ? `/dashboard?${currentQuery}` : "/dashboard";
    navigate(
      buildCouncilApplicationReviewHref({ applicationId, returnTo, viewOnly: true }),
    );
  };

  return (
    <div className="space-y-4">
      <Card>
        <CardHeader>
          <CardTitle>Tìm kiếm hồ sơ sáng kiến</CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="grid grid-cols-1 gap-4 md:grid-cols-3 lg:grid-cols-3">
            <div className="space-y-2">
              <Label htmlFor="name">Tên sáng kiến</Label>
              <Input id="name" value={nameInput} onChange={(e) => setNameInput(e.target.value)} placeholder="Nhập tên sáng kiến" />
            </div>
            <div className="space-y-2">
              <Label>Đơn vị</Label>
              <Select
                value={filters.subjectId || ALL_OPTION_VALUE}
                onValueChange={(v) => setFilter("subjectId", v === ALL_OPTION_VALUE ? "" : v)}
              >
                <SelectTrigger><SelectValue placeholder="Chọn" /></SelectTrigger>
                <SelectContent>
                  <SelectItem value={ALL_OPTION_VALUE}>Tất cả</SelectItem>
                  {DEPARTMENT_OPTIONS.map((option) => (
                    <SelectItem key={option.value} value={option.value}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-2">
              <Label>Năm</Label>
              <Select value={filters.conferenceId || ALL_OPTION_VALUE} onValueChange={(v) => setFilter("conferenceId", v === ALL_OPTION_VALUE ? "" : v)}>
                <SelectTrigger><SelectValue placeholder="Chọn" /></SelectTrigger>
                <SelectContent>
                  <SelectItem value={ALL_OPTION_VALUE}>Tất cả</SelectItem>
                  {(conferencesQuery.data ?? []).map((option) => <SelectItem key={option.value} value={option.value}>{option.label}</SelectItem>)}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-2">
              <Label>Trạng thái</Label>
              <Select value={filters.status || ALL_OPTION_VALUE} onValueChange={(v) => setFilter("status", v === ALL_OPTION_VALUE ? "" : v)}>
                <SelectTrigger><SelectValue placeholder="Chọn" /></SelectTrigger>
                <SelectContent>
                  <SelectItem value={ALL_OPTION_VALUE}>Tất cả</SelectItem>
                  {STATUS_OPTIONS.map((option) => <SelectItem key={option.value} value={option.value}>{option.label}</SelectItem>)}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-2">
              <Label htmlFor="date-from">Ngày gởi</Label>
              <Input
                id="date-from"
                inputMode="numeric"
                autoComplete="off"
                placeholder="dd/mm/yyyy"
                value={dateFromText}
                onChange={(e) => setDateFromText(e.target.value)}
                onBlur={() => {
                  const iso = parseDdMmYyyyToIso(dateFromText);
                  setFilter("dateFrom", iso);
                  setDateFromText(iso ? isoDateToDdMmYyyy(iso) : "");
                }}
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="author-name">Tác giả</Label>
              <Input
                id="author-name"
                value={authorInput}
                onChange={(e) => setAuthorInput(e.target.value)}
                placeholder="Nhập tên tác giả"
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="reviewer-name">Người đánh giá</Label>
              <Input
                id="reviewer-name"
                value={reviewerInput}
                onChange={(e) => setReviewerInput(e.target.value)}
                placeholder="Nhập tên người đánh giá"
              />
            </div>
            <div className="space-y-2">
              <Label>Người phụ trách</Label>
              <SearchableSelect value={filters.supervisorId} placeholder="Chọn người phụ trách" options={supervisorsQuery.data ?? []} onValueChange={(v) => setFilter("supervisorId", v)} />
            </div>
            <div className="space-y-2">
              <Label>Nhóm sáng kiến</Label>
              <Select value={filters.topicTypeId || ALL_OPTION_VALUE} onValueChange={(v) => setFilter("topicTypeId", v === ALL_OPTION_VALUE ? "" : v)}>
                <SelectTrigger><SelectValue placeholder="Chọn" /></SelectTrigger>
                <SelectContent>
                  <SelectItem value={ALL_OPTION_VALUE}>Tất cả</SelectItem>
                  {GROUP_OPTIONS.map((option) => (
                    <SelectItem key={option.value} value={option.value}>
                      {option.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>

          <div className="flex items-center gap-3">
            <Button onClick={() => setFilters((prev) => ({ ...prev, page: 1 }))}>Tìm</Button>
            <Button variant="ghost" onClick={handleReset}>Xóa bộ lọc</Button>
          </div>
        </CardContent>
      </Card>

      <div className="flex items-center justify-between">
        <h3 className="font-semibold">Kết quả tìm ({pagination.totalItems})</h3>
        <Button onClick={exportExcel} className="bg-green-600 hover:bg-green-700" disabled={isExportingExcel}>
          {isExportingExcel ? <Loader2 className="h-4 w-4 animate-spin" /> : null}
          Xuất Excel
        </Button>
      </div>

      <div className="overflow-x-auto rounded-md border">
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead className="w-[50px]">STT</TableHead>
              <TableHead className="w-[120px]"><button type="button" onClick={() => toggleSort("submittedDate")} className="inline-flex items-center gap-1">Ngày gởi <ArrowUpDown className="h-3 w-3" /></button></TableHead>
              <TableHead className="min-w-[250px]"><button type="button" onClick={() => toggleSort("name")} className="inline-flex items-center gap-1">Tên sáng kiến <ArrowUpDown className="h-3 w-3" /></button></TableHead>
              <TableHead className="min-w-[160px]"><button type="button" onClick={() => toggleSort("author")} className="inline-flex items-center gap-1">Tác giả <ArrowUpDown className="h-3 w-3" /></button></TableHead>
              <TableHead className="w-[140px]">Đơn vị</TableHead>
              <TableHead className="w-[120px]">Người đánh giá</TableHead>
              <TableHead className="w-[120px]">Người phụ trách</TableHead>
              <TableHead className="w-[110px]">Nhóm sáng kiến</TableHead>
              <TableHead className="w-[110px]">Trạng thái</TableHead>
              <TableHead className="w-[60px] text-center">Minh chứng</TableHead>
              <TableHead className="w-[180px] text-center">Đánh giá</TableHead>
              <TableHead className="w-[100px] text-center">Xem hồ sơ</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {applicationsQuery.isLoading ? (
              <TableRow><TableCell colSpan={12} className="py-10 text-center text-muted-foreground">Đang tải dữ liệu...</TableCell></TableRow>
            ) : dataWithDocxDemo.length === 0 ? (
              <TableRow><TableCell colSpan={12} className="py-10 text-center text-muted-foreground">Không có dữ liệu</TableCell></TableRow>
            ) : (
              dataWithDocxDemo.map((item, index) => {
                const stt = (pagination.page - 1) * pagination.pageSize + index + 1;
                return (
                  <ApplicationIdeaRow
                    key={item.id}
                    item={item}
                    stt={stt}
                    statusBadge={statusBadge}
                    status={getStatus(item)}
                    departmentLabel={optionLabel(DEPARTMENT_OPTIONS, item.subjectId)}
                    groupLabel={optionLabel(GROUP_OPTIONS, item.groupId) || item.topicType || ""}
                    evidenceCell={
                      <EvidenceFilesTableCell
                        item={item}
                        caseId={item.draftCaseId || item.draft_case_id}
                      />
                    }
                    onApprove={(id) => handleReviewAction(id, "approved")}
                    onReject={(id) => handleReviewAction(id, "rejected")}
                    onReview={handleOpenReview}
                    formatDate={formatDate}
                  />
                );
              })
            )}
          </TableBody>
        </Table>
      </div>

      <div className="flex flex-col justify-between gap-3 text-sm text-muted-foreground sm:flex-row sm:items-center">
        <div>Trang {pagination.page} / {Math.max(1, pagination.totalPages)} | Hiển thị {pagination.pageSize} / {pagination.totalItems} kết quả</div>
        <div className="flex items-center gap-2">
          <Select value={String(filters.pageSize)} onValueChange={(v) => setFilters((prev) => ({ ...prev, pageSize: Number(v), page: 1 }))}>
            <SelectTrigger className="w-[90px]"><SelectValue /></SelectTrigger>
            <SelectContent>
              {[10, 20, 50, 100].map((size) => <SelectItem key={size} value={String(size)}>{size}</SelectItem>)}
            </SelectContent>
          </Select>
          <Button variant="outline" size="sm" onClick={() => setFilter("page", Math.max(1, filters.page - 1))} disabled={filters.page <= 1}>Trước</Button>
          <Button variant="outline" size="sm" onClick={() => setFilter("page", Math.min(pagination.totalPages, filters.page + 1))} disabled={filters.page >= pagination.totalPages}>Sau</Button>
        </div>
      </div>
    </div>
  );
}
