import * as React from "react"
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form"
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { Check, ChevronsUpDown, Loader, UserRoundPlus, AlertTriangle, Users, UserMinus } from "lucide-react"
import { cn } from "@/lib/utils"
import { toast } from "sonner"
import { Alert, AlertDescription } from "@/components/ui/alert"
import { Badge } from "@/components/ui/badge"

import { Textarea } from "@/components/ui/textarea"
import { Company } from "@/db/schema/companies"
import { getAllCompanies } from "@/lib/admin-users/service"
import {
  Popover,
  PopoverTrigger,
  PopoverContent,
} from "@/components/ui/popover"
import {
  Command,
  CommandInput,
  CommandList,
  CommandGroup,
  CommandItem,
  CommandEmpty,
} from "@/components/ui/command"
import { assignRolesToUsers, getAllRoleView, checkMultipleRegularEvaluationRolesAssigned } from "@/lib/roles/services"
import { Role, RoleView } from "@/db/schema/users"
import { type UserView } from "@/db/schema/users"
import { type Row } from "@tanstack/react-table"
import { createRoleAssignmentSchema, CreateRoleAssignmentSchema, createRoleSchema, CreateRoleSchema } from "@/lib/roles/validations"
import { MultiSelect } from "@/components/ui/multi-select"

interface AssignRoleDialogProps
  extends React.ComponentPropsWithoutRef<typeof Dialog> {
  users: Row<UserView>["original"][]
  roles: RoleView[]
}

// 역할 상태 타입 정의
type RoleAssignmentStatus = 'all' | 'some' | 'none'

interface RoleAnalysis {
  roleId: string
  roleName: string
  status: RoleAssignmentStatus
  assignedUserCount: number
  totalUserCount: number
}

export function AssignRoleDialog({ users, roles }: AssignRoleDialogProps) {
  const [open, setOpen] = React.useState(false)
  const [isAddPending, startAddTransition] = React.useTransition()
  const [loading, setLoading] = React.useState(false)
  const [regularEvaluationAssigned, setRegularEvaluationAssigned] = React.useState<{[roleId: string]: boolean}>({})
  const [isCheckingRegularEvaluation, setIsCheckingRegularEvaluation] = React.useState(false)

  // 메모이제이션된 필터링된 역할들
  const partnersRoles = React.useMemo(() => 
    roles.filter(v => v.domain === "partners"), [roles])
  
  const evcpRoles = React.useMemo(() => 
    roles.filter(v => v.domain === "evcp"), [roles])

  // 메모이제이션된 evcp 사용자들
  const evcpUsers = React.useMemo(() => 
    users.filter(v => v.user_domain === "evcp"), [users])

  // 선택된 사용자들의 역할 분석
  const roleAnalysis = React.useMemo((): RoleAnalysis[] => {
    if (evcpUsers.length === 0) return []

    const analysis = evcpRoles.map(role => {
      const assignedUsers = evcpUsers.filter(user => 
        user.roles && user.roles.includes(role.name)
      )
      
      const assignedUserCount = assignedUsers.length
      const totalUserCount = evcpUsers.length
      
      let status: RoleAssignmentStatus
      if (assignedUserCount === totalUserCount) {
        status = 'all'
      } else if (assignedUserCount > 0) {
        status = 'some'
      } else {
        status = 'none'
      }

      return {
        roleId: String(role.id),
        roleName: role.name,
        status,
        assignedUserCount,
        totalUserCount
      }
    })

    console.log('Role analysis:', analysis)
    return analysis
  }, [evcpUsers, evcpRoles])

  // 초기 선택된 역할들 (모든 사용자에게 할당된 역할들 + 일부에게 할당된 역할들)
  const initialSelectedRoles = React.useMemo(() => {
    const selected = roleAnalysis
      .filter(analysis => analysis.status === 'all' || analysis.status === 'some')
      .map(analysis => analysis.roleId)
    
    console.log('Initial selected roles:', selected)
    return selected
  }, [roleAnalysis])

  const form = useForm<CreateRoleAssignmentSchema>({
    resolver: zodResolver(createRoleAssignmentSchema),
    defaultValues: {
      evcpRoles: [],
    },
  })

  const handleDialogOpenChange = React.useCallback((nextOpen: boolean) => {
    if (!nextOpen) {
      // 다이얼로그가 닫힐 때 리셋
      form.reset({
        evcpRoles: [],
      })
      setRegularEvaluationAssigned({})
    }
    setOpen(nextOpen)
  }, [form])

  // 선택된 evcpRoles 감시 - 메모이제이션
  const selectedEvcpRoles = form.watch("evcpRoles")
  const memoizedSelectedEvcpRoles = React.useMemo(() => 
    selectedEvcpRoles || [], [selectedEvcpRoles])

  // 정기평가 role들 찾기 - 의존성 수정
  const selectedRegularEvaluationRoles = React.useMemo(() => {
    return memoizedSelectedEvcpRoles.filter(roleId => {
      const role = evcpRoles.find(r => String(r.id) === roleId)
      return role && role.name.includes("정기평가")
    })
  }, [memoizedSelectedEvcpRoles, evcpRoles])

  // 정기평가 role 할당 상태 체크 (debounced)
  React.useEffect(() => {
    if (selectedRegularEvaluationRoles.length === 0) {
      setRegularEvaluationAssigned({})
      return
    }

    const timeoutId = setTimeout(async () => {
      setIsCheckingRegularEvaluation(true)
      try {
        const roleIds = selectedRegularEvaluationRoles.map(roleId => Number(roleId))
        const assignmentStatus = await checkMultipleRegularEvaluationRolesAssigned(roleIds)
        
        const stringKeyStatus: {[roleId: string]: boolean} = {}
        Object.entries(assignmentStatus).forEach(([roleId, isAssigned]) => {
          stringKeyStatus[roleId] = isAssigned
        })
        
        setRegularEvaluationAssigned(stringKeyStatus)
      } catch (error) {
        console.error("정기평가 role 할당 상태 체크 실패:", error)
        toast.error("정기평가 role 상태 확인에 실패했습니다")
      } finally {
        setIsCheckingRegularEvaluation(false)
      }
    }, 500)

    return () => clearTimeout(timeoutId)
  }, [selectedRegularEvaluationRoles])

  // 할당 불가능한 정기평가 role 확인
  const blockedRegularEvaluationRoles = React.useMemo(() => {
    return selectedRegularEvaluationRoles.filter(roleId => 
      regularEvaluationAssigned[roleId] === true
    )
  }, [selectedRegularEvaluationRoles, regularEvaluationAssigned])

  // 제출 가능 여부
  const canSubmit = React.useMemo(() => 
    blockedRegularEvaluationRoles.length === 0, [blockedRegularEvaluationRoles])

  // MultiSelect options 메모이제이션 - 상태 정보와 함께 표시
  const multiSelectOptions = React.useMemo(() => {
    return evcpRoles.map((role) => {
      const analysis = roleAnalysis.find(a => a.roleId === String(role.id))
      
      let statusSuffix = ''
      if (analysis) {
        if (analysis.status === 'all') {
          statusSuffix = ` (모든 사용자 ${analysis.assignedUserCount}/${analysis.totalUserCount})`
        } else if (analysis.status === 'some') {
          statusSuffix = ` (일부 사용자 ${analysis.assignedUserCount}/${analysis.totalUserCount})`
        }
      }

      return { 
        value: String(role.id), 
        label: role.name + statusSuffix,
        disabled: role.name.includes("정기평가") && regularEvaluationAssigned[String(role.id)] === true
      }
    })
  }, [evcpRoles, roleAnalysis, regularEvaluationAssigned])

  const onSubmit = React.useCallback(async (data: CreateRoleAssignmentSchema) => {
    startAddTransition(async () => {
      if (evcpUsers.length === 0) return

      try {
        const selectedRoleIds = data.evcpRoles.map(v => Number(v))
        const userIds = evcpUsers.map(v => v.user_id)
        
        // assignRolesToUsers는 이미 기존 관계를 삭제하고 새로 삽입하므로
        // 최종 선택된 역할들만 전달하면 됩니다
        const result = await assignRolesToUsers(selectedRoleIds, userIds)
        
        if (result.error) {
          toast.error(`역할 업데이트 실패: ${result.error}`)
          return
        }

        form.reset()
        setOpen(false)
        setRegularEvaluationAssigned({})
        
        // 변경사항 계산해서 피드백
        const initialRoleIds = initialSelectedRoles.map(v => Number(v))
        const addedRoles = selectedRoleIds.filter(roleId => !initialRoleIds.includes(roleId))
        const removedRoles = initialRoleIds.filter(roleId => !selectedRoleIds.includes(roleId))
        
        if (addedRoles.length > 0 && removedRoles.length > 0) {
          toast.success(`역할이 성공적으로 업데이트되었습니다 (추가: ${addedRoles.length}, 제거: ${removedRoles.length})`)
        } else if (addedRoles.length > 0) {
          toast.success(`${addedRoles.length}개 역할이 성공적으로 추가되었습니다`)
        } else if (removedRoles.length > 0) {
          toast.success(`${removedRoles.length}개 역할이 성공적으로 제거되었습니다`)
        } else {
          toast.info("변경사항이 없습니다")
        }
      } catch (error) {
        console.error("역할 업데이트 실패:", error)
        toast.error("역할 업데이트에 실패했습니다")
      }
    })
  }, [evcpUsers, form, initialSelectedRoles])

  // 정기평가 role 관련 경고 메시지 생성
  const regularEvaluationWarning = React.useMemo(() => {
    if (selectedRegularEvaluationRoles.length === 0) return null

    if (isCheckingRegularEvaluation) {
      return (
        <Alert key="checking">
          <Loader className="h-4 w-4 animate-spin" />
          <AlertDescription>
            정기평가 role 할당 상태를 확인하고 있습니다...
          </AlertDescription>
        </Alert>
      )
    }

    if (blockedRegularEvaluationRoles.length > 0) {
      const blockedRoleNames = blockedRegularEvaluationRoles.map(roleId => {
        const role = evcpRoles.find(r => String(r.id) === roleId)
        return role?.name || roleId
      })

      return (
        <Alert key="blocked" variant="destructive">
          <AlertTriangle className="h-4 w-4" />
          <AlertDescription>
            <strong>할당 불가:</strong> 다음 정기평가 role이 이미 다른 유저에게 할당되어 있습니다: 
            <br />
            <strong>{blockedRoleNames.join(", ")}</strong>
            <br />
            정기평가 role은 한 명의 유저에게만 할당할 수 있습니다.
          </AlertDescription>
        </Alert>
      )
    }

    if (selectedRegularEvaluationRoles.length > 0) {
      const availableRoleNames = selectedRegularEvaluationRoles.map(roleId => {
        const role = evcpRoles.find(r => String(r.id) === roleId)
        return role?.name || roleId
      })

      return (
        <Alert key="available">
          <Check className="h-4 w-4" />
          <AlertDescription>
            정기평가 role을 할당할 수 있습니다: <strong>{availableRoleNames.join(", ")}</strong>
          </AlertDescription>
        </Alert>
      )
    }

    return null
  }, [
    selectedRegularEvaluationRoles, 
    isCheckingRegularEvaluation, 
    blockedRegularEvaluationRoles, 
    evcpRoles
  ])

  // 현재 역할 상태 요약
  const roleStatusSummary = React.useMemo(() => {
    const allRoles = roleAnalysis.filter(r => r.status === 'all').length
    const someRoles = roleAnalysis.filter(r => r.status === 'some').length
    const totalRoles = roleAnalysis.length

    return { allRoles, someRoles, totalRoles }
  }, [roleAnalysis])

  return (
    <Dialog open={open} onOpenChange={handleDialogOpenChange}>
      <DialogTrigger asChild>
        <Button variant="default" size="sm">
          <UserRoundPlus className="mr-2 size-4" aria-hidden="true" />
          역할 편집 ({users.length}명)
        </Button>
      </DialogTrigger>

      <DialogContent className="max-w-2xl">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <Users className="size-5" />
            {evcpUsers.length}명 사용자의 역할 편집
          </DialogTitle>
          <DialogDescription className="space-y-2">
            <div>선택된 사용자들의 역할을 편집할 수 있습니다. 기존 역할 상태가 표시됩니다.</div>
            <div className="flex gap-2 text-sm">
              <Badge variant="secondary">
                공통 역할: {roleStatusSummary.allRoles}개
              </Badge>
              <Badge variant="outline">
                일부 역할: {roleStatusSummary.someRoles}개
              </Badge>
              <Badge variant="secondary">
                전체 역할: {roleStatusSummary.totalRoles}개
              </Badge>
            </div>
          </DialogDescription>
        </DialogHeader>

        <Form {...form}>
          <form onSubmit={form.handleSubmit(onSubmit)}>
            <div className="space-y-4 py-4">
              {/* evcp 롤 선택 */}
              {evcpUsers.length > 0 && (
                <FormField
                  control={form.control}
                  name="evcpRoles"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel className="flex items-center gap-2">
                        eVCP 역할 선택
                        <span className="text-sm text-muted-foreground">
                          (체크: 할당됨, 해제: 제거됨)
                        </span>
                      </FormLabel>
                      <FormControl>
                        <MultiSelect
                          key={`multiselect-${open}-${initialSelectedRoles.join(',')}`}
                          options={multiSelectOptions}
                          onValueChange={(values) => {
                            console.log('MultiSelect value changed:', values)
                            field.onChange(values)
                          }}
                          defaultValue={initialSelectedRoles}
                        />
                      </FormControl>
                      <FormMessage />
                      
                      {/* 역할 상태 설명 */}
                      <div className="text-sm text-muted-foreground space-y-1">
                        <div>• <strong>모든 사용자</strong>: 선택된 모든 사용자에게 할당된 역할</div>
                        <div>• <strong>일부 사용자</strong>: 일부 사용자에게만 할당된 역할</div>
                        <div>• 역할을 체크하면 모든 사용자에게 할당되고, 해제하면 모든 사용자에서 제거됩니다</div>
                      </div>
                      
                      {/* 정기평가 관련 경고 메시지 */}
                      {regularEvaluationWarning && (
                        <div className="mt-2">
                          {regularEvaluationWarning}
                        </div>
                      )}
                    </FormItem>
                  )}
                />
              )}
            </div>

            <DialogFooter>
              <Button
                type="button"
                variant="outline"
                onClick={() => setOpen(false)}
                disabled={isAddPending}
              >
                취소
              </Button>
              <Button
                type="submit"
                disabled={
                  form.formState.isSubmitting || 
                  isAddPending || 
                  !canSubmit ||
                  isCheckingRegularEvaluation
                }
              >
                {isAddPending && (
                  <Loader
                    className="mr-2 size-4 animate-spin"
                    aria-hidden="true"
                  />
                )}
                역할 업데이트
              </Button>
            </DialogFooter>
          </form>
        </Form>
      </DialogContent>
    </Dialog>
  )
}