import React, { useState, useCallback, useEffect, useRef, useMemo } from 'react';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '../ui/table';
import { Input } from '../ui/input';
import { Button } from '../ui/button';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '../ui/select';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '../ui/dialog';
import { Plus, Pencil, MoreHorizontal, Trash2, ClipboardList } from 'lucide-react';
import { toast } from 'sonner';
import { skipCountForPage } from '../../lib/paginationQuery';
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from '../ui/pagination';
import { getLabelTemplates, getLabelTemplate, deleteLabelTemplate } from '../../services/labelTemplateService';
import { getLocations } from '../../services/locationService';
import { appliedLocationToEditor, type LabelTemplateDto } from '../../types/labelTemplate';
import { LabelTemplateEditor } from './LabelTemplateEditor';
import { LabelTemplateDataEntryView } from './LabelTemplateDataEntryView';
import type { LabelElement, LabelTemplate } from '../../types/labelTemplate';
import type { LocationDto } from '../../types/location';

function toDisplay(v: string | null | undefined): string {
  const s = (v ?? "").trim();
  return s ? s : "None";
}

function locationColumnText(t: LabelTemplateDto, locations: LocationDto[]): string {
  const mode = appliedLocationToEditor(t);
  if (mode === "ALL") return "All";
  const ids = t.appliedLocationIds ?? [];
  if (ids.length === 0) return "Specified (0)";
  const names = ids.map(
    (id) => locations.find((l) => l.id === id)?.locationName?.trim() || id,
  );
  if (names.length <= 2) return names.join(", ");
  return `${names.slice(0, 2).join(", ")} +${names.length - 2}`;
}

/** 列表行：名称列 ← templateName / name */
function templateListDisplayName(t: LabelTemplateDto): string {
  const n = (t.templateName ?? t.name ?? "").trim();
  return n ? n : "None";
}

/** 列表行：模板编码列 ← templateCode / id */
function templateListDisplayCode(t: LabelTemplateDto): string {
  const c = (t.templateCode ?? t.id ?? "").trim();
  return c ? c : "None";
}

/** 列表行：门店展示 ← locationText，缺省时再推导 */
function templateListDisplayLocation(t: LabelTemplateDto, locations: LocationDto[]): string {
  const lt = (t.locationText ?? "").trim();
  if (lt) return lt;
  return locationColumnText(t, locations);
}

/** 列表行：元素数量 ← contentsCount / elements.length */
function templateListContentsCount(t: LabelTemplateDto): number {
  if (typeof t.contentsCount === "number") return t.contentsCount;
  return t.elements?.length ?? 0;
}

/** 列表行：尺寸 ← sizeText，缺省时用 width×height unit */
function templateListDisplaySize(t: LabelTemplateDto): string {
  const st = (t.sizeText ?? "").trim();
  if (st) return st;
  const w = t.width;
  const h = t.height;
  const u = t.unit;
  if (w != null && h != null && u) return `${w}×${h} ${u}`;
  return "None";
}

export function LabelTemplatesView() {
  const [templates, setTemplates] = useState<LabelTemplateDto[]>([]);
  const [viewMode, setViewMode] = useState<'list' | 'editor' | 'dataEntry'>('list');
  const [editingTemplateId, setEditingTemplateId] = useState<string | null>(null);
  const [dataEntryTemplateCode, setDataEntryTemplateCode] = useState<string | null>(null);
  const [initialTemplate, setInitialTemplate] = useState<LabelTemplate | null>(null);
  const [loading, setLoading] = useState(false);
  const [total, setTotal] = useState(0);
  const [refreshSeq, setRefreshSeq] = useState(0);
  const [actionsOpenForId, setActionsOpenForId] = useState<string | null>(null);
  const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
  const [deletingTemplate, setDeletingTemplate] = useState<LabelTemplateDto | null>(null);

  const [keyword, setKeyword] = useState('');
  const [locationFilter, setLocationFilter] = useState('all');
  const [labelTypeFilter, setLabelTypeFilter] = useState<string>('all');
  const [stateFilter, setStateFilter] = useState<string>('all');

  const [pageIndex, setPageIndex] = useState(1);
  const [pageSize, setPageSize] = useState(10);
  const [locations, setLocations] = useState<LocationDto[]>([]);

  const abortRef = useRef<AbortController | null>(null);
  const keywordTimerRef = useRef<number | null>(null);
  const [debouncedKeyword, setDebouncedKeyword] = useState('');

  useEffect(() => {
    if (keywordTimerRef.current) window.clearTimeout(keywordTimerRef.current);
    keywordTimerRef.current = window.setTimeout(() => setDebouncedKeyword(keyword.trim()), 300);
    return () => {
      if (keywordTimerRef.current) window.clearTimeout(keywordTimerRef.current);
    };
  }, [keyword]);

  const totalPages = Math.max(1, Math.ceil(total / pageSize));

  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const res = await getLocations({ skipCount: 1, maxResultCount: 500 });
        if (!cancelled) setLocations(res.items ?? []);
      } catch {
        if (!cancelled) setLocations([]);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, []);

  useEffect(() => {
    setPageIndex(1);
  }, [debouncedKeyword, locationFilter, labelTypeFilter, stateFilter, pageSize]);

  useEffect(() => {
    if (viewMode !== 'list') return;

    const run = async () => {
      abortRef.current?.abort();
      const ac = new AbortController();
      abortRef.current = ac;

      setLoading(true);
      try {
        const skipCount = skipCountForPage(pageIndex);
        const res = await getLabelTemplates(
          {
            skipCount,
            maxResultCount: pageSize,
            keyword: debouncedKeyword || undefined,
            locationId: locationFilter !== 'all' ? locationFilter : undefined,
            labelType: labelTypeFilter !== 'all' ? (labelTypeFilter as any) : undefined,
            state: stateFilter === 'all' ? undefined : stateFilter === 'true',
          },
          ac.signal,
        );

        setTemplates(res.items ?? []);
        setTotal(res.totalCount ?? 0);
      } catch (e: any) {
        if (e?.name === 'AbortError') return;
        toast.error('Failed to load label templates.', {
          description: e?.message ? String(e.message) : 'Please try again.',
        });
        setTemplates([]);
        setTotal(0);
      } finally {
        setLoading(false);
      }
    };

    run();
    return () => abortRef.current?.abort();
  }, [debouncedKeyword, locationFilter, labelTypeFilter, stateFilter, pageIndex, pageSize, refreshSeq, viewMode]);

  const refreshList = () => setRefreshSeq((x) => x + 1);

  const handleNewTemplate = () => {
    setEditingTemplateId(null);
    setInitialTemplate(null);
    setViewMode('editor');
  };

  const handleEditTemplate = async (templateCode: string) => {
    setEditingTemplateId(templateCode);
    setLoading(true);
    try {
      const apiTemplate = await getLabelTemplate(templateCode);
      // 转换 API 返回的 DTO 到编辑器需要的格式
      const editorTemplate: LabelTemplate = {
        id: apiTemplate.id,
        name: (apiTemplate.name ?? apiTemplate.templateName ?? '').trim() || '未命名模板',
        labelType: (apiTemplate.labelType as any) ?? 'PRICE',
        unit: (apiTemplate.unit as any) ?? 'cm',
        width: apiTemplate.width ?? 6,
        height: apiTemplate.height ?? 4,
        appliedLocation: appliedLocationToEditor(apiTemplate),
        appliedLocationIds: [...(apiTemplate.appliedLocationIds ?? [])],
        showRuler: apiTemplate.showRuler ?? true,
        showGrid: apiTemplate.showGrid ?? true,
        elements: (apiTemplate.elements ?? []).map((raw, idx) => {
          const el = raw as LabelElement;
          const en = (el.elementName ?? "").trim();
          return {
            ...el,
            elementName: en || `element${idx + 1}`,
          };
        }),
      };
      setInitialTemplate(editorTemplate);
      setViewMode('editor');
    } catch (e: any) {
      toast.error('Failed to load template.', {
        description: e?.message ? String(e.message) : 'Please try again.',
      });
    } finally {
      setLoading(false);
    }
  };

  const handleCloseEditor = () => {
    setViewMode('list');
    setEditingTemplateId(null);
    setInitialTemplate(null);
  };

  const handleOpenDataEntry = (templateCode: string) => {
    setActionsOpenForId(null);
    setDataEntryTemplateCode(templateCode);
    setViewMode('dataEntry');
  };

  const handleCloseDataEntry = () => {
    setViewMode('list');
    setDataEntryTemplateCode(null);
  };

  const openDelete = (template: LabelTemplateDto) => {
    setActionsOpenForId(null);
    setDeletingTemplate(template);
    setIsDeleteDialogOpen(true);
  };

  if (viewMode === 'editor') {
    return (
      <div className="h-[calc(100vh-8rem)] min-h-[500px] flex flex-col">
        <LabelTemplateEditor
          templateId={editingTemplateId}
          initialTemplate={initialTemplate}
          onClose={handleCloseEditor}
          onSaved={refreshList}
        />
      </div>
    );
  }

  if (viewMode === 'dataEntry' && dataEntryTemplateCode) {
    return (
      <div className="h-[calc(100vh-8rem)] min-h-[500px] flex flex-col pt-2">
        <LabelTemplateDataEntryView
          templateCode={dataEntryTemplateCode}
          onBack={handleCloseDataEntry}
        />
      </div>
    );
  }

  return (
    <div className="h-full flex flex-col">
      <div className="pb-4">
        <div className="flex flex-col gap-4">
          <div className="flex flex-nowrap items-center gap-3">
            <Input
              placeholder="Search"
              value={keyword}
              onChange={(e) => setKeyword(e.target.value)}
              style={{ height: 40, boxSizing: 'border-box' }}
              className="bg-white border border-gray-300 rounded-md w-40 shrink-0 placeholder:text-gray-500"
            />
            <Select value={locationFilter} onValueChange={setLocationFilter}>
              <SelectTrigger className="bg-white border border-gray-300 rounded-md w-[150px] shrink-0" style={{ height: 40, boxSizing: 'border-box' }}>
                <SelectValue placeholder="Location" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All Locations</SelectItem>
                {locations.map((loc) => (
                  <SelectItem key={loc.id} value={loc.id}>
                    {toDisplay(loc.locationName ?? loc.locationCode ?? loc.id)}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <Select value={labelTypeFilter} onValueChange={setLabelTypeFilter}>
              <SelectTrigger className="bg-white border border-gray-300 rounded-md w-[150px] shrink-0" style={{ height: 40, boxSizing: 'border-box' }}>
                <SelectValue placeholder="Label Type" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All Types</SelectItem>
                <SelectItem value="PRICE">PRICE</SelectItem>
                <SelectItem value="NUTRITION">NUTRITION</SelectItem>
                <SelectItem value="SHIPPING">SHIPPING</SelectItem>
              </SelectContent>
            </Select>
            <Select value={stateFilter} onValueChange={setStateFilter}>
              <SelectTrigger className="bg-white border border-gray-300 rounded-md w-[150px] shrink-0" style={{ height: 40, boxSizing: 'border-box' }}>
                <SelectValue placeholder="State" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All States</SelectItem>
                <SelectItem value="true">Active</SelectItem>
                <SelectItem value="false">Inactive</SelectItem>
              </SelectContent>
            </Select>
            <div className="flex-1" />
            <Button
              className="bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-md h-10 px-6 shrink-0"
              onClick={handleNewTemplate}
            >
              New Label Template <Plus className="ml-1 w-4 h-4" />
            </Button>
          </div>
        </div>
      </div>

      <div className="flex-1 overflow-auto pt-6">
        <div className="rounded-md border bg-white shadow-sm">
          <Table>
            <TableHeader>
              <TableRow className="bg-gray-50 hover:bg-gray-50">
                <TableHead className="font-bold text-gray-900 w-[180px]">Label Template</TableHead>
                <TableHead className="font-bold text-gray-900 w-[120px]">Template Code</TableHead>
                <TableHead className="font-bold text-gray-900 w-[120px]">Location</TableHead>
                <TableHead className="font-bold text-gray-900 w-[100px]">Label Type</TableHead>
                <TableHead className="font-bold text-gray-900">Contents</TableHead>
                <TableHead className="font-bold text-gray-900 w-[150px]">Size</TableHead>
                <TableHead className="font-bold text-gray-900 text-center w-[100px]">Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {loading ? (
                <TableRow>
                  <TableCell colSpan={7} className="text-center text-sm text-gray-500 py-10">
                    Loading...
                  </TableCell>
                </TableRow>
              ) : templates.length === 0 ? (
                <TableRow>
                  <TableCell colSpan={7} className="text-center text-sm text-gray-500 py-10">
                    No templates yet. Click &quot;New Label Template&quot; to create one.
                  </TableCell>
                </TableRow>
              ) : (
                templates.map((t) => (
                  <TableRow key={t.id} className="hover:bg-gray-50">
                    <TableCell className="font-medium whitespace-nowrap overflow-hidden text-ellipsis max-w-[180px]">
                      {templateListDisplayName(t)}
                    </TableCell>
                    <TableCell className="text-gray-600 whitespace-nowrap overflow-hidden text-ellipsis max-w-[140px]">
                      {templateListDisplayCode(t)}
                    </TableCell>
                    <TableCell className="whitespace-nowrap overflow-hidden text-ellipsis max-w-[140px]">
                      {toDisplay(templateListDisplayLocation(t, locations))}
                    </TableCell>
                    <TableCell className="whitespace-nowrap">{toDisplay(t.labelType)}</TableCell>
                    <TableCell className="text-sm text-gray-600 whitespace-nowrap">
                      {templateListContentsCount(t)} element(s)
                    </TableCell>
                    <TableCell className="whitespace-nowrap overflow-hidden text-ellipsis max-w-[160px]">
                      {templateListDisplaySize(t)}
                    </TableCell>
                    <TableCell className="text-center">
                      <Popover
                        open={actionsOpenForId === t.id}
                        onOpenChange={(open) => setActionsOpenForId(open ? t.id : null)}
                      >
                        <PopoverTrigger asChild>
                          <Button
                            type="button"
                            variant="ghost"
                            size="icon"
                            className="h-8 w-8"
                            aria-label="Row actions"
                          >
                            <MoreHorizontal className="h-4 w-4 text-gray-500" />
                          </Button>
                        </PopoverTrigger>
                        <PopoverContent align="end" className="w-48 p-1">
                          <Button
                            type="button"
                            variant="ghost"
                            className="w-full justify-start gap-2 h-9 px-2 font-normal"
                            title="录入数据"
                            onClick={() => handleOpenDataEntry(t.id)}
                          >
                            <ClipboardList className="w-4 h-4" />
                            Enter Data
                          </Button>
                          <Button
                            type="button"
                            variant="ghost"
                            className="w-full justify-start gap-2 h-9 px-2 font-normal"
                            onClick={() => handleEditTemplate(t.id)}
                          >
                            <Pencil className="w-4 h-4" />
                            Edit
                          </Button>
                          <Button
                            type="button"
                            variant="ghost"
                            className="w-full justify-start gap-2 h-9 px-2 font-normal text-red-600 hover:text-red-700 hover:bg-red-50"
                            onClick={() => openDelete(t)}
                          >
                            <Trash2 className="w-4 h-4 shrink-0" />
                            Delete
                          </Button>
                        </PopoverContent>
                      </Popover>
                    </TableCell>
                  </TableRow>
                ))
              )}
            </TableBody>
          </Table>
        </div>
      </div>

      <div className="pt-4">
        <div className="flex items-center justify-between text-sm text-gray-600">
          <div>
            Showing {total === 0 ? 0 : (pageIndex - 1) * pageSize + 1}-
            {Math.min(pageIndex * pageSize, total)} of {total}
          </div>
          <div className="flex items-center gap-3">
            <Select value={String(pageSize)} onValueChange={(v) => setPageSize(Number(v))}>
              <SelectTrigger className="w-[110px] h-9 rounded-md border border-gray-300 bg-white text-gray-900">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {[10, 20, 50].map((n) => (
                  <SelectItem key={n} value={String(n)}>
                    {n} / page
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <Pagination className="mx-0 w-auto justify-end">
              <PaginationContent>
                <PaginationItem>
                  <PaginationPrevious
                    href="#"
                    size="default"
                    onClick={(e) => {
                      e.preventDefault();
                      setPageIndex((p) => Math.max(1, p - 1));
                    }}
                    aria-disabled={pageIndex <= 1}
                    className={pageIndex <= 1 ? "pointer-events-none opacity-50" : ""}
                  />
                </PaginationItem>
                <PaginationItem>
                  <PaginationLink
                    href="#"
                    isActive
                    size="default"
                    onClick={(e) => e.preventDefault()}
                  >
                    Page {pageIndex} / {totalPages}
                  </PaginationLink>
                </PaginationItem>
                <PaginationItem>
                  <PaginationNext
                    href="#"
                    size="default"
                    onClick={(e) => {
                      e.preventDefault();
                      setPageIndex((p) => Math.min(totalPages, p + 1));
                    }}
                    aria-disabled={pageIndex >= totalPages}
                    className={pageIndex >= totalPages ? "pointer-events-none opacity-50" : ""}
                  />
                </PaginationItem>
              </PaginationContent>
            </Pagination>
          </div>
        </div>
      </div>

      <DeleteLabelTemplateDialog
        open={isDeleteDialogOpen}
        template={deletingTemplate}
        onOpenChange={(open) => {
          setIsDeleteDialogOpen(open);
          if (!open) setDeletingTemplate(null);
        }}
        onDeleted={refreshList}
      />
    </div>
  );
}

function DeleteLabelTemplateDialog({
  open,
  template,
  onOpenChange,
  onDeleted,
}: {
  open: boolean;
  template: LabelTemplateDto | null;
  onOpenChange: (open: boolean) => void;
  onDeleted: () => void;
}) {
  const [submitting, setSubmitting] = useState(false);

  const name = useMemo(() => {
    const n = (template?.templateName ?? template?.name ?? "").trim();
    return n || (template?.templateCode ?? template?.id ?? "").trim() || "this template";
  }, [template]);

  const submit = async () => {
    if (!template?.id) return;
    setSubmitting(true);
    try {
      await deleteLabelTemplate(template.id);
      toast.success("Label template deleted.", {
        description: "The label template has been removed successfully.",
      });
      onOpenChange(false);
      onDeleted();
    } catch (e: any) {
      toast.error("Failed to delete label template.", {
        description: e?.message ? String(e.message) : "Please try again.",
      });
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-none" style={{ width: "30%" }}>
        <DialogHeader>
          <DialogTitle>Delete Label Template</DialogTitle>
          <DialogDescription>This action cannot be undone.</DialogDescription>
        </DialogHeader>

        <div className="text-sm text-gray-700">
          Are you sure you want to delete <span className="font-medium">{name}</span>?
        </div>

        <DialogFooter className="flex-row flex-wrap justify-end">
          <Button className="min-w-24" variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            className="min-w-24 gap-2"
            variant="destructive"
            disabled={submitting}
            onClick={submit}
          >
            <Trash2 className="h-4 w-4 shrink-0" />
            {submitting ? "Deleting..." : "Delete"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
