'use client';

import React, { useState, useEffect, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import {
  ChevronDown,
  ChevronRight,
  Shield,
  ArrowLeft,
  Trash2,
  Save,
  CheckCircle2,
  XCircle,
  RotateCcw,
  Loader2,
  Plus,
} from 'lucide-react';
import { useMenuStore } from '@/stores/menuStore';
import { DetailPageSkeleton } from '@/components/ui/skeleton';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Card, CardContent } from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import { Switch } from '@/components/ui/switch';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table';
import { DeleteConfirmDialog } from '@/components/ui/confirm-dialog';
import { useDeleteDialog } from '@/hooks/useDeleteDialog';
import { PageHeader } from '@/components/organisms/PageHeader';
import { PageLayout } from '@/components/organisms/PageLayout';
import { ServerErrorPage } from '@/components/common/ServerErrorPage';
import { toast } from 'sonner';
import type { Role, MenuTreeItem, PermissionMatrix, PermissionType } from './types';
import {
  fetchRole,
  createRole,
  updateRole,
  deleteRole,
  fetchPermissionMenus,
  fetchPermissionMatrix,
  togglePermission,
  allowAllPermissions,
  denyAllPermissions,
  resetPermissions,
} from './actions';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { usePermissionContext } from '@/contexts/PermissionContext';

// 플랫 배열을 트리 구조로 변환
interface FlatMenuItem {
  id: number;
  name: string;
  code: string;
  parent_id: number | null;
  depth: number;
  sort_order: number;
  has_children?: boolean;
}

function buildMenuTree(flatMenus: FlatMenuItem[]): MenuTreeItem[] {
  const menuMap = new Map<number, MenuTreeItem>();
  const roots: MenuTreeItem[] = [];

  // 1. 모든 메뉴를 맵에 저장
  flatMenus.forEach(menu => {
    menuMap.set(menu.id, {
      id: menu.id,
      name: menu.name,
      code: menu.code,
      parent_id: menu.parent_id,
      depth: menu.depth,
      sort_order: menu.sort_order,
      children: [],
    });
  });

  // 2. 부모-자식 관계 설정
  flatMenus.forEach(menu => {
    const treeItem = menuMap.get(menu.id)!;
    if (menu.parent_id === null) {
      roots.push(treeItem);
    } else {
      const parent = menuMap.get(menu.parent_id);
      if (parent) {
        parent.children = parent.children || [];
        parent.children.push(treeItem);
      }
    }
  });

  // 3. 정렬 (sort_order 기준)
  const sortMenus = (menus: MenuTreeItem[]) => {
    menus.sort((a, b) => a.sort_order - b.sort_order);
    menus.forEach(menu => {
      if (menu.children && menu.children.length > 0) {
        sortMenus(menu.children);
      }
    });
  };
  sortMenus(roots);

  return roots;
}

interface PermissionDetailClientProps {
  permissionId: string;
  isNew?: boolean;
  mode?: 'view' | 'edit';
}

// 권한 타입
const PERMISSION_TYPES: PermissionType[] = ['view', 'create', 'update', 'delete', 'approve', 'export', 'manage'];
const PERMISSION_LABELS_MAP: Record<PermissionType, string> = {
  view: '조회',
  create: '생성',
  update: '수정',
  delete: '삭제',
  approve: '승인',
  export: '내보내기',
  manage: '관리',
};

export function PermissionDetailClient({ permissionId, isNew = false, mode = 'view' }: PermissionDetailClientProps) {
  const router = useRouter();
  const sidebarCollapsed = useMenuStore((state) => state.sidebarCollapsed);
  const { reloadPermissions } = usePermissionContext();

  // 역할 데이터
  const [role, setRole] = useState<Role | null>(null);
  const [name, setName] = useState('');
  const [description, setDescription] = useState('');
  const [isHidden, setIsHidden] = useState(false);

  // 권한 매트릭스 데이터
  const [menuTree, setMenuTree] = useState<MenuTreeItem[]>([]);
  const [, setPermissionTypes] = useState<string[]>([]);
  const [matrix, setMatrix] = useState<PermissionMatrix | null>(null);

  // UI 상태
  const [expandedMenus, setExpandedMenus] = useState<Set<number>>(new Set());
  const [isLoading, setIsLoading] = useState(true);
  const [isSaving, setIsSaving] = useState(false);
  const [isTogglingPermission, setIsTogglingPermission] = useState(false);

  // 데이터 로드
  const loadData = useCallback(async () => {
    setIsLoading(true);

    try {
      // 메뉴 트리 로드
      const menusResult = await fetchPermissionMenus();
      if (menusResult.success && menusResult.data) {
        // 플랫 배열을 트리 구조로 변환
        const treeMenus = buildMenuTree(menusResult.data.menus as FlatMenuItem[]);
        setMenuTree(treeMenus);
        setPermissionTypes(menusResult.data.permission_types);
      } else {
        console.error('[PermissionDetail] Failed to load menus:', menusResult.error);
        toast.error(menusResult.error || '메뉴 트리 로드 실패');
      }

      if (!isNew) {
        // 기존 역할 로드
        const roleResult = await fetchRole(parseInt(permissionId));
        if (roleResult.success && roleResult.data) {
          setRole(roleResult.data);
          setName(roleResult.data.name);
          setDescription(roleResult.data.description || '');
          setIsHidden(roleResult.data.is_hidden);
        } else {
          toast.error(roleResult.error || '역할 조회 실패');
        }

        // 권한 매트릭스 로드
        const matrixResult = await fetchPermissionMatrix(parseInt(permissionId));
        if (matrixResult.success && matrixResult.data) {
          setMatrix(matrixResult.data);
        }
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error(error instanceof Error ? error.message : '데이터 로드 실패');
    } finally {
      setIsLoading(false);
    }
  }, [permissionId, isNew]);

  useEffect(() => {
    loadData();
  }, [loadData]);

  // 뒤로가기
  const handleBack = useCallback(() => {
    router.push('/settings/permissions');
  }, [router]);

  // 메뉴 접기/펼치기
  const toggleMenuExpand = (menuId: number) => {
    setExpandedMenus(prev => {
      const newSet = new Set(prev);
      if (newSet.has(menuId)) {
        newSet.delete(menuId);
      } else {
        newSet.add(menuId);
      }
      return newSet;
    });
  };

  // 새 역할 저장
  const handleSaveNew = async () => {
    if (!name.trim()) {
      toast.error('역할명을 입력해주세요.');
      return;
    }

    setIsSaving(true);
    try {
      const result = await createRole({
        name: name.trim(),
        description: description.trim() || undefined,
        is_hidden: isHidden,
      });

      if (result.success && result.data) {
        toast.success('역할이 생성되었습니다.');
        router.replace(`/settings/permissions/${result.data.id}`);
      } else {
        toast.error(result.error || '역할 생성 실패');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error(error instanceof Error ? error.message : '저장 중 오류 발생');
    } finally {
      setIsSaving(false);
    }
  };

  // 역할 정보 업데이트
  const handleUpdateRole = async () => {
    if (!role) return;

    setIsSaving(true);
    try {
      const result = await updateRole(role.id, {
        name: name.trim(),
        description: description.trim() || undefined,
        is_hidden: isHidden,
      });

      if (result.success && result.data) {
        setRole(result.data);
        toast.success('역할 정보가 수정되었습니다.');
      } else {
        toast.error(result.error || '역할 수정 실패');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error(error instanceof Error ? error.message : '수정 중 오류 발생');
    } finally {
      setIsSaving(false);
    }
  };

  // 권한 토글
  const handlePermissionToggle = async (menuId: number, permType: string) => {
    if (!role || isTogglingPermission) return;

    setIsTogglingPermission(true);
    try {
      const result = await togglePermission(role.id, menuId, permType);

      if (result.success && result.data) {
        // 매트릭스 새로고침
        const matrixResult = await fetchPermissionMatrix(role.id);
        if (matrixResult.success && matrixResult.data) {
          setMatrix(matrixResult.data);
        }

        // 하위 메뉴 전파 알림
        if (result.data.propagated_to && result.data.propagated_to.length > 0) {
          toast.info(`하위 ${result.data.propagated_to.length}개 메뉴에도 적용되었습니다.`);
        }
      } else {
        toast.error(result.error || '권한 변경 실패');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error(error instanceof Error ? error.message : '권한 변경 중 오류 발생');
    } finally {
      setIsTogglingPermission(false);
    }
  };

  // 전체 허용
  const handleAllowAll = async () => {
    if (!role) return;

    setIsSaving(true);
    try {
      const result = await allowAllPermissions(role.id);
      if (result.success) {
        toast.success('모든 권한이 허용되었습니다.');
        const matrixResult = await fetchPermissionMatrix(role.id);
        if (matrixResult.success && matrixResult.data) {
          setMatrix(matrixResult.data);
        }
      } else {
        toast.error(result.error || '전체 허용 실패');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error(error instanceof Error ? error.message : '전체 허용 중 오류 발생');
    } finally {
      setIsSaving(false);
    }
  };

  // 전체 거부
  const handleDenyAll = async () => {
    if (!role) return;

    setIsSaving(true);
    try {
      const result = await denyAllPermissions(role.id);
      if (result.success) {
        toast.success('모든 권한이 거부되었습니다.');
        const matrixResult = await fetchPermissionMatrix(role.id);
        if (matrixResult.success && matrixResult.data) {
          setMatrix(matrixResult.data);
        }
      } else {
        toast.error(result.error || '전체 거부 실패');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error(error instanceof Error ? error.message : '전체 거부 중 오류 발생');
    } finally {
      setIsSaving(false);
    }
  };

  // 기본값 초기화
  const handleReset = async () => {
    if (!role) return;

    setIsSaving(true);
    try {
      const result = await resetPermissions(role.id);
      if (result.success) {
        toast.success('기본 권한으로 초기화되었습니다. (조회만 허용)');
        const matrixResult = await fetchPermissionMatrix(role.id);
        if (matrixResult.success && matrixResult.data) {
          setMatrix(matrixResult.data);
        }
      } else {
        toast.error(result.error || '초기화 실패');
      }
    } catch (error) {
      if (isNextRedirectError(error)) throw error;
      toast.error(error instanceof Error ? error.message : '초기화 중 오류 발생');
    } finally {
      setIsSaving(false);
    }
  };

  // 삭제
  const deleteDialog = useDeleteDialog({
    onDelete: async (id) => deleteRole(Number(id)),
    onSuccess: handleBack,
    entityName: '역할',
  });

  // 메뉴의 권한 상태 가져오기
  const getMenuPermission = (menuId: number, permType: string): boolean => {
    if (!matrix || !matrix.permissions) return false;
    const menuPerm = matrix.permissions[menuId];
    return menuPerm?.[permType as PermissionType] || false;
  };

  // 메뉴 행 렌더링 (재귀)
  const renderMenuRows = (menus: MenuTreeItem[], depth = 0): React.ReactElement[] => {
    const rows: React.ReactElement[] = [];

    menus.forEach(menu => {
      const hasChildren = menu.children && menu.children.length > 0;
      const isExpanded = expandedMenus.has(menu.id);

      rows.push(
        <TableRow key={menu.id} className="hover:bg-muted/50">
          <TableCell className="font-medium" style={{ paddingLeft: `${depth * 24 + 16}px` }}>
            <div className="flex items-center gap-2">
              {hasChildren && (
                <button
                  onClick={() => toggleMenuExpand(menu.id)}
                  className="p-0.5 hover:bg-accent rounded"
                >
                  {isExpanded ? (
                    <ChevronDown className="h-4 w-4" />
                  ) : (
                    <ChevronRight className="h-4 w-4" />
                  )}
                </button>
              )}
              {!hasChildren && <span className="w-5" />}
              <span className={depth > 0 ? 'text-muted-foreground' : ''}>
                {depth > 0 && '- '}
                {menu.name}
              </span>
            </div>
          </TableCell>
          {PERMISSION_TYPES.map(pt => (
            <TableCell key={pt} className="text-center">
              <Checkbox
                checked={getMenuPermission(menu.id, pt)}
                onCheckedChange={() => handlePermissionToggle(menu.id, pt)}
                disabled={isTogglingPermission || isNew}
              />
            </TableCell>
          ))}
        </TableRow>
      );

      // 자식 메뉴
      if (hasChildren && isExpanded && menu.children) {
        rows.push(...renderMenuRows(menu.children, depth + 1));
      }
    });

    return rows;
  };

  // 로딩 상태
  if (isLoading) {
    return (
      <PageLayout>
        <DetailPageSkeleton />
      </PageLayout>
    );
  }

  // 역할을 찾지 못한 경우
  if (!isNew && !role) {
    return (
      <ServerErrorPage
        title="역할을 불러올 수 없습니다"
        message="역할을 찾을 수 없습니다."
        showBackButton={true}
        showHomeButton={true}
      />
    );
  }

  return (
    <PageLayout>
      {/* 페이지 헤더 */}
      <PageHeader
        title={isNew ? '역할 등록' : mode === 'edit' ? '역할 수정' : '역할 상세'}
        description={isNew ? '새 역할을 등록합니다' : mode === 'edit' ? '역할 정보를 수정합니다' : '역할 정보와 권한을 관리합니다'}
        icon={Shield}
      />

      <div className="space-y-6 pb-24">
      {/* 기본 정보 */}
      <Card>
        <CardContent className="p-6">
          <h3 className="text-lg font-semibold mb-4">기본 정보</h3>
          <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
            <div className="space-y-2">
              <Label htmlFor="role-name">역할명 *</Label>
              <Input
                id="role-name"
                value={name}
                onChange={(e) => setName(e.target.value)}
                placeholder="역할명을 입력하세요"
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="role-description">설명</Label>
              <Input
                id="role-description"
                value={description}
                onChange={(e) => setDescription(e.target.value)}
                placeholder="역할 설명을 입력하세요"
              />
            </div>
            <div className="space-y-2">
              <Label htmlFor="role-hidden">숨김 설정</Label>
              <div className="flex items-center gap-2 pt-2">
                <Switch
                  id="role-hidden"
                  checked={isHidden}
                  onCheckedChange={async (checked) => {
                    setIsHidden(checked);
                    // 기존 역할인 경우 즉시 저장
                    if (role) {
                      try {
                        const result = await updateRole(role.id, { is_hidden: checked });
                        if (result.success && result.data) {
                          setRole(result.data);
                          toast.success(checked ? '역할이 숨김 처리되었습니다.' : '역할이 공개되었습니다.');
                        } else {
                          // 실패 시 롤백
                          setIsHidden(!checked);
                          toast.error(result.error || '숨김 설정 변경 실패');
                        }
                      } catch (error) {
                        if (isNextRedirectError(error)) throw error;
                        setIsHidden(!checked);
                        toast.error('숨김 설정 변경 중 오류 발생');
                      }
                    }
                  }}
                  disabled={isSaving}
                />
                <span className="text-sm text-muted-foreground">
                  {isHidden ? '숨김 (사용자에게 표시 안함)' : '공개'}
                </span>
              </div>
            </div>
          </div>
        </CardContent>
      </Card>

      {/* 권한 매트릭스 (기존 역할만 표시) */}
      {!isNew && (
        <Card>
          <CardContent className="p-6">
            <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4">
              <h3 className="text-lg font-semibold">메뉴별 권한</h3>
              <div className="flex flex-wrap gap-2">
                <Button
                  variant="outline"
                  size="sm"
                  onClick={handleAllowAll}
                  disabled={isSaving}
                >
                  <CheckCircle2 className="h-4 w-4 mr-2" />
                  전체 허용
                </Button>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={handleDenyAll}
                  disabled={isSaving}
                >
                  <XCircle className="h-4 w-4 mr-2" />
                  전체 거부
                </Button>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={handleReset}
                  disabled={isSaving}
                >
                  <RotateCcw className="h-4 w-4 mr-2" />
                  기본값 초기화
                </Button>
              </div>
            </div>
            <div className="overflow-x-auto">
              <Table>
                <TableHeader>
                  <TableRow className="border-b">
                    <TableHead className="w-64 py-4">메뉴</TableHead>
                    {PERMISSION_TYPES.map(pt => (
                      <TableHead key={pt} className="text-center w-24 py-4">
                        <span className="text-sm font-medium">{PERMISSION_LABELS_MAP[pt]}</span>
                      </TableHead>
                    ))}
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {renderMenuRows(menuTree)}
                </TableBody>
              </Table>
            </div>
            {isTogglingPermission && (
              <div className="absolute inset-0 bg-background/50 flex items-center justify-center">
                <Loader2 className="h-6 w-6 animate-spin" />
              </div>
            )}
          </CardContent>
        </Card>
      )}

      {/* 새 역할 안내 */}
      {isNew && (
        <Card>
          <CardContent className="p-6">
            <div className="text-center text-muted-foreground py-8">
              <p>역할을 저장한 후 메뉴별 권한을 설정할 수 있습니다.</p>
            </div>
          </CardContent>
        </Card>
      )}
      </div>

      {/* 하단 액션 버튼 (sticky) */}
      <div className={`fixed bottom-4 left-4 right-4 px-4 py-3 bg-background/95 backdrop-blur rounded-xl border shadow-lg z-50 transition-all duration-300 md:bottom-6 md:px-6 md:right-[48px] ${sidebarCollapsed ? 'md:left-[156px]' : 'md:left-[316px]'} flex items-center justify-between`}>
        <Button variant="outline" onClick={handleBack} size="sm" className="md:size-default">
          <ArrowLeft className="h-4 w-4 md:mr-2" />
          <span className="hidden md:inline">목록으로</span>
        </Button>
        <div className="flex items-center gap-1 md:gap-2">
          {isNew ? (
            <Button onClick={handleSaveNew} disabled={isSaving} size="sm" className="md:size-default">
              {isSaving ? (
                <Loader2 className="h-4 w-4 animate-spin" />
              ) : (
                <>
                  <Plus className="h-4 w-4 md:mr-2" />
                  <span className="hidden md:inline">등록</span>
                </>
              )}
            </Button>
          ) : (
            <>
              <Button variant="outline" onClick={handleUpdateRole} disabled={isSaving} size="sm" className="md:size-default">
                {isSaving ? (
                  <Loader2 className="h-4 w-4 animate-spin" />
                ) : (
                  <>
                    <Save className="h-4 w-4 md:mr-2" />
                    <span className="hidden md:inline">정보 저장</span>
                  </>
                )}
              </Button>
              <Button
                onClick={() => {
                  reloadPermissions();
                  toast.success('권한 정보가 저장되었습니다.');
                }}
                size="sm"
                className="md:size-default"
              >
                <Shield className="h-4 w-4 md:mr-2" />
                <span className="hidden md:inline">권한 정보 저장</span>
              </Button>
              <Button
                variant="outline"
                onClick={() => role && deleteDialog.single.open(String(role.id))}
                size="sm"
                className="text-destructive hover:bg-destructive hover:text-destructive-foreground md:size-default"
              >
                <Trash2 className="h-4 w-4 md:mr-2" />
                <span className="hidden md:inline">삭제</span>
              </Button>
            </>
          )}
        </div>
      </div>

      {/* 삭제 확인 다이얼로그 */}
      {!isNew && role && (
        <DeleteConfirmDialog
          open={deleteDialog.single.isOpen}
          onOpenChange={deleteDialog.single.onOpenChange}
          onConfirm={deleteDialog.single.confirm}
          title="역할 삭제"
          description={
            <>
              &quot;{role.name}&quot; 역할을 삭제하시겠습니까?
              <br />
              <span className="text-destructive">
                이 역할을 사용 중인 사원이 있으면 해당 사원의 역할이 초기화됩니다.
              </span>
            </>
          }
          loading={deleteDialog.isPending}
        />
      )}
    </PageLayout>
  );
}