/* eslint-disable @typescript-eslint/no-explicit-any */

'use client';

/* IMPORT */
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 { ChevronsUpDown, X } from 'lucide-react';
import {
  Collapsible,
  CollapsibleContent,
  CollapsibleTrigger,
} from '@/components/ui/collapsible';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle
} from '@/components/ui/dialog';
import {
  Dropzone,
  DropzoneDescription,
  DropzoneInput,
  DropzoneTitle,
  DropzoneUploadIcon,
  DropzoneZone,
} from '@/components/ui/dropzone';
import {
  FileList,
  FileListAction,
  FileListDescription,
  FileListHeader,
  FileListIcon,
  FileListInfo,
  FileListItem,
  FileListName,
  FileListSize,
} from '@/components/ui/file-list';
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '@/components/ui/form';
import { format } from 'date-fns';
import { getProcurementManagerList, modifyRiskEvents } from '../service';
import { RISK_ADMIN_COMMENTS_LIST } from '@/config/risksConfig';
import { ScrollArea } from '@/components/ui/scroll-area';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue
} from '@/components/ui/select';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Textarea } from '@/components/ui/textarea';
import { toast } from 'sonner';
import { type RisksView, type User } from '@/db/schema';
import { useForm } from 'react-hook-form';
import { useEffect, useMemo, useState, useTransition } from 'react';
import UserComboBox from './user-combo-box';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
import { se } from 'date-fns/locale';

// ----------------------------------------------------------------------------------------------------

/* TYPES */
const risksMailFormSchema = z.object({
  managerId: z.number({ required_error: '구매 담당자를 반드시 선택해야 해요.' }),
  adminComment: z.string().min(1, { message: '구매 담당자 의견을 반드시 작성해야 해요.' }),
  attachment: z
    .instanceof(File)
    .refine((file) => file.size <= 10485760, {
      message: '파일 크기는 10MB를 초과할 수 없어요.',
    })
    .optional(),
});

type RisksMailFormData = z.infer<typeof risksMailFormSchema>;

interface RisksMailDialogProps {
  open: boolean,
  onOpenChange: (open: boolean) => void,
  riskDataList: RisksView[],
  onSuccess: () => void,
};

// ----------------------------------------------------------------------------------------------------

/* CONSTATNS */
const ALWAYS_CHECKED_TYPES = ['종합등급', '신용등급', '현금흐름등급', 'WATCH등급'];

// ----------------------------------------------------------------------------------------------------

/* RISKS MAIL DIALOG COPONENT */
function RisksMailDialog(props: RisksMailDialogProps) {
  const { open, onOpenChange, riskDataList, onSuccess } = props;
  const riskDataMap = useMemo(() => {
    return riskDataList.reduce((acc, item) => {
      if (!acc[item.vendorId]) {
        acc[item.vendorId] = [];
      }
      acc[item.vendorId].push(item);
      return acc;
    }, {} as Record<string, typeof riskDataList>);
  }, [riskDataList]);
  const [isPending, startTransition] = useTransition();
  const form = useForm<RisksMailFormData>({
    resolver: zodResolver(risksMailFormSchema),
    defaultValues: {
      managerId: undefined,
      adminComment: '',
      attachment: undefined,
    },
  });
  const selectedFile = form.watch('attachment');
  const [selectedVendorId, setSelectedVendorId] = useState<number | null>(riskDataList[0]?.vendorId ?? null);
  const [selectedCommentType, setSelectedCommentType] = useState('');
  const [managerList, setManagerList] = useState<Partial<User>[]>([]);
  const [isLoadingManagerList, setIsLoadingManagerList] = useState(false);
  const [riskCheckMap, setRiskCheckMap] = useState<Record<string, boolean>>({});

  useEffect(() => {
    if (!selectedVendorId) {
      return;
    }

    const eventTypeMap = (riskDataMap[selectedVendorId] || []).reduce<Record<string, RisksView[]>>((acc, item) => {
      if (!acc[item.eventType]) {
        acc[item.eventType] = [];
      }
      acc[item.eventType].push(item);
      return acc;
    }, {});

    const initialRiskCheckMap: Record<string, boolean> = {};
    Object.keys(eventTypeMap).forEach((type) => {
      initialRiskCheckMap[type] = true;
    });

    setRiskCheckMap(initialRiskCheckMap);
    setSelectedCommentType('기타');
    form.reset({
      managerId: undefined,
      adminComment: '',
      attachment: undefined,
    });
  }, [open, selectedVendorId]);
  
  useEffect(() => {
    if (open) {
      startTransition(async () => {
        try {
          setIsLoadingManagerList(true);
          form.reset({
            managerId: undefined,
            adminComment: '',
            attachment: undefined,
          });
          setSelectedCommentType('기타');
          const managerList = await getProcurementManagerList();
          setManagerList(managerList);
        } catch (error) {
          console.error('Error in Loading Risk Event for Managing:', error);
          toast.error(error instanceof Error ? error.message : '구매 담당자 목록을 불러오는 데 실패했어요.');
        } finally {
          setIsLoadingManagerList(false);
        }
      });
    }
  }, [open, form]);

  const formatBusinessNumber = (numberString: string) => {
    if (!numberString) {
      return '정보 없음';
    }
    return /^\d{10}$/.test(numberString)
      ? `${numberString.slice(0, 3)}-${numberString.slice(3, 5)}-${numberString.slice(5)}`
      : numberString;
  };

  const handleCheckboxChange = (type: string) => {
    if (ALWAYS_CHECKED_TYPES.includes(type)) {
      return;
    }
    setRiskCheckMap(prev => ({
      ...prev,
      [type]: !prev[type],
    }));
  };

  const handleFileChange = (files: File[]) => {
    if (files.length === 0) {
      return;
    }
    const file = files[0];
    const maxFileSize = 10 * 1024 * 1024
    if (file.size > maxFileSize) {
      toast.error('파일 크기는 10MB를 초과할 수 없어요.');
      return;
    }
    form.setValue('attachment', file);
    form.clearErrors('attachment');
  }

  const removeFile = () => {
    form.resetField('attachment');
  }

  const onSubmit = async (data: RisksMailFormData) => {
    startTransition(async () => {
      try {
        if (!selectedVendorId) {
          throw Error('선택된 협력업체가 존재하지 않아요.');
        }

        const newRiskEventData = {
          managerId: data.managerId ,
          adminComment: data.adminComment,
        };
        
        await Promise.all(
          (riskDataMap[selectedVendorId] ?? []).map(riskEvent =>
            modifyRiskEvents(riskEvent.id, newRiskEventData)
          )
        );

        const eventTypeMap = (riskDataMap[selectedVendorId] || []).reduce<Record<string, RisksView[]>>((acc, item) => {
          if (!acc[item.eventType]) {
            acc[item.eventType] = [];
          }
          acc[item.eventType].push(item);
          return acc;
        }, {});
        const filteredEventTypeMap: Record<string, RisksView[]> = {};
        Object.entries(eventTypeMap).forEach(([type, items]) => {
          if (ALWAYS_CHECKED_TYPES.includes(type)) {
            return;
          }
          if (riskCheckMap[type]) {
            filteredEventTypeMap[type] = items;
          }
        });
        
        const formData = new FormData();
        formData.append('vendorId', String(selectedVendorId));
        formData.append('managerId', String(data.managerId));
        formData.append('adminComment', data.adminComment);
        if (data.attachment) {
          formData.append('attachment', data.attachment);
        }
        formData.append('selectedEventTypeMap', JSON.stringify(filteredEventTypeMap));

        const res = await fetch('/api/risks/send-risk-email', {
          method: 'POST',
          body: formData,
        });

        if (!res.ok) {
          const errorData = await res.json();
          throw new Error(errorData.message || '리스크 알림 메일 전송에 실패했어요.');
        }

        toast.success('리스크 알림 메일이 구매 담당자에게 발송되었어요.');
        onSuccess();
      } catch (error) {
        console.error('Error in Saving Risk Event:', error);
        toast.error(
          error instanceof Error ? error.message : '리스크 알림 메일 발송 중 오류가 발생했어요.',
        );
      }
    })
  }

  if (!open) {
    return null;
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-w-4xl max-h-[90vh] flex flex-col">
        <DialogHeader className="flex-shrink-0">
          <DialogTitle className="font-bold">
            리스크 알림 메일 발송
          </DialogTitle>
          <DialogDescription>
            구매 담당자에게 리스크 알림 메일을 발송합니다.
          </DialogDescription>
        </DialogHeader>
        <Tabs
          value={selectedVendorId !== null ? String(selectedVendorId) : undefined}
          onValueChange={(value) => setSelectedVendorId(value ? Number(value) : null)}
          className="mb-4"
        >
          <TabsList>
            {Object.entries(riskDataMap).map(([vendorId, items]) => (
              <TabsTrigger key={vendorId} value={vendorId}>
                {items[0].vendorName}
              </TabsTrigger>
            ))}
          </TabsList>
          {Object.entries(riskDataMap).map(([vendorId, items]) => (
            <TabsContent key={vendorId} value={vendorId} className="overflow-y-auto max-h-[60vh]">
              <Form {...form}>
                <form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col flex-1 min-h-0">
                  <ScrollArea className="flex-1 pr-4 overflow-y-auto">
                    <div className="space-y-6">
                      <Card className="w-full">
                        <CardHeader>
                          <CardTitle>협력업체 정보</CardTitle>
                        </CardHeader>
                        <CardContent className="space-y-4 text-sm text-muted-foreground">
                          <div className="grid grid-cols-2 gap-4">
                            <div>
                              <span className="font-medium text-foreground">협력업체명: </span>
                              {items[0].vendorName ?? '정보 없음'}
                            </div>
                            <div>
                              <span className="font-medium text-foreground">사업자등록번호: </span>
                              {formatBusinessNumber(items[0].businessNumber ?? '')}
                            </div>
                            <div>
                              <span className="font-medium text-foreground">협력업체 코드: </span>
                              {items[0].vendorCode ?? '정보 없음'}
                            </div>
                          </div>
                        </CardContent>
                      </Card>
                      <Card className="w-full">
                        <CardHeader>
                          <CardTitle>리스크 정보</CardTitle>
                          <CardDescription>메일로 전송할 리스크 정보를 선택하세요.</CardDescription>
                        </CardHeader>
                        <CardContent className="space-y-4">
                          {Object.entries(
                            items?.reduce<Record<string, typeof items>>((acc, item) => {
                              if (!acc[item.eventType]) acc[item.eventType] = [];
                              acc[item.eventType].push(item);
                              return acc;
                            }, {}) || {}
                          ).map(([eventType, groupedItems]) => (
                            <Collapsible key={eventType} defaultOpen={false} className="rounded-md border gap-2 p-4 text-sm">
                              <div className="flex items-center justify-between gap-4 px-4">
                                <div className="flex items-center gap-2">
                                  <Checkbox
                                    checked={riskCheckMap[eventType]}
                                    disabled={ALWAYS_CHECKED_TYPES.includes(eventType)}
                                    onCheckedChange={() => handleCheckboxChange(eventType)}
                                  />
                                  <span className="text-sm font-semibold">{eventType}</span>
                                </div>
                                <CollapsibleTrigger className="flex justify-between items-center">
                                  <Button type="button" variant="ghost" size="icon" className="size-8">
                                    <ChevronsUpDown />
                                  </Button>
                                </CollapsibleTrigger>
                              </div>
                              <CollapsibleContent>
                                {/* Table로 변경할 것 */}
                                <div className="flex items-center justify-between rounded-md border my-2 px-4 py-2 text-sm">
                                  <div className="font-bold">신용평가사</div>
                                  <div className="font-bold">상세 내용</div>
                                  <div className="font-bold">발생일자</div>
                                </div>
                                {groupedItems.map(item => (
                                  <div key={item.id} className="flex items-center justify-between rounded-md border gap-2 px-4 py-2 text-sm">
                                    <Badge variant="secondary">{item.provider}</Badge>
                                    <div className="text-sm text-muted-foreground">{item.content}</div>
                                    <div>{format(item.occuredAt, 'yyyy-MM-dd')}</div>
                                  </div>
                                ))}
                              </CollapsibleContent>
                            </Collapsible>
                          ))}
                        </CardContent>
                      </Card>
                      <Card className="w-full">
                        <CardHeader>
                          <CardTitle>메일 발송 정보</CardTitle>
                        </CardHeader>
                        <CardContent className="space-y-4">
                          <div className="grid grid-cols-2 gap-4">
                            <FormField
                              control={form.control}
                              name="managerId"
                              render={({ field }) => (
                                <FormItem>
                                  <FormLabel>구매 담당자</FormLabel>
                                    <UserComboBox
                                      users={managerList}
                                      value={field.value ?? null}
                                      onChange={field.onChange}
                                      placeholder={isLoadingManagerList ? '구매 담당자 로딩 중...' : '구매 담당자 선택...'}
                                      disabled={isPending || isLoadingManagerList}
                                    />
                                  <FormControl>
                                  </FormControl>
                                  <FormMessage />
                                </FormItem>
                              )}
                            />
                            <div className="flex flex-col gap-4">
                              <FormItem>
                                <FormLabel>관리 담당자 의견</FormLabel>
                                <FormControl>
                                  <Select
                                    onValueChange={(value) => {
                                      setSelectedCommentType(value);
                                      if (value !== '기타') {
                                        form.setValue('adminComment', value);
                                      } else {
                                        form.setValue('adminComment', '');
                                      }
                                    }}
                                    value={selectedCommentType}
                                  >
                                    <SelectTrigger>
                                      <SelectValue placeholder="의견 선택" />
                                    </SelectTrigger>
                                    <SelectContent>
                                      {RISK_ADMIN_COMMENTS_LIST.map((comment) => (
                                        <SelectItem key={comment} value={comment}>
                                          {comment}
                                        </SelectItem>
                                      ))}
                                    </SelectContent>
                                  </Select>
                                </FormControl>
                              </FormItem>
                              {selectedCommentType === '기타' && (
                                <FormField
                                  control={form.control}
                                  name="adminComment"
                                  render={({ field }) => (
                                    <FormItem>
                                      <FormControl>
                                        <Textarea
                                          placeholder="관리 담당자 의견을 입력하세요."
                                          {...field}
                                          value={field.value ?? ''}
                                        />
                                      </FormControl>
                                      <FormMessage />
                                    </FormItem>
                                  )}
                                />
                              )}
                            </div>
                          </div>
                          <FormField
                            control={form.control}
                            name="attachment"
                            render={() => (
                              <FormItem>
                                <FormLabel>첨부파일</FormLabel>
                                <FormControl>
                                  <div className="space-y-3">
                                    <Dropzone
                                      onDrop={(acceptedFiles) => {
                                        handleFileChange(acceptedFiles)
                                      }}
                                      accept={{
                                        'application/pdf': ['.pdf'],
                                        'application/msword': ['.doc'],
                                        'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'],
                                        'application/vnd.ms-excel': ['.xls'],
                                        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'],
                                        'application/vnd.ms-powerpoint': ['.ppt'],
                                        'application/vnd.openxmlformats-officedocument.presentationml.presentation': ['.pptx'],
                                        'application/zip': ['.zip'],
                                        'application/x-rar-compressed': ['.rar']
                                      }}
                                      maxSize={10 * 1024 * 1024}
                                      multiple={false}
                                      disabled={isPending}
                                    >
                                      <DropzoneZone className="flex flex-col items-center gap-2">
                                        <DropzoneUploadIcon />
                                        <DropzoneTitle>클릭하여 파일 선택 또는 드래그 앤 드롭</DropzoneTitle>
                                        <DropzoneDescription>
                                          PDF, DOC, XLS, PPT 등 (최대 10MB, 파일 1개)
                                        </DropzoneDescription>
                                        <DropzoneInput />
                                      </DropzoneZone>
                                    </Dropzone>
                                    {selectedFile && (
                                      <div className="space-y-2">
                                        <FileListHeader>
                                          선택된 파일
                                        </FileListHeader>
                                        <FileList>
                                          <FileListItem className="flex items-center justify-between gap-3">
                                            <FileListIcon />
                                            <FileListInfo>
                                              <FileListName>{selectedFile.name}</FileListName>
                                              <FileListDescription>
                                                <FileListSize>{selectedFile.size}</FileListSize>
                                              </FileListDescription>
                                            </FileListInfo>
                                            <FileListAction
                                              onClick={removeFile}
                                              disabled={isPending}
                                            >
                                              <X className="h-4 w-4" />
                                            </FileListAction>
                                          </FileListItem>
                                        </FileList>
                                      </div>
                                    )}
                                  </div>
                                </FormControl>
                                <FormMessage />
                              </FormItem>
                            )}
                          />
                        </CardContent>
                      </Card>
                    </div>
                  </ScrollArea>
                  <DialogFooter className="flex-shrink-0 mt-4 pt-4 border-t">
                    <Button
                      type="button"
                      variant="outline"
                      onClick={() => onOpenChange(false)}
                      disabled={isPending}
                    >
                      취소
                    </Button>
                    <Button type="submit" disabled={isPending || isLoadingManagerList}>
                      {isLoadingManagerList ? '로딩 중...' : isPending ? '저장 중...' : '메일 발송'}
                    </Button>
                  </DialogFooter>
                </form>
              </Form>
            </TabsContent>
          ))}
        </Tabs>
      </DialogContent>
    </Dialog>
  )
}

// ----------------------------------------------------------------------------------------------------

/* EXPORT */
export default RisksMailDialog;
