import LoaderIcon from '@/components/icons/loader-icon';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormMessage,
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { closeTicket } from '@/data/user/ticket/close-ticket';
import { sendUserTicketReply } from '@/data/user/ticket/send-ticket-reply';
import { useApiSWR } from '@/hooks/useSWR';
import { SharedData } from '@/types';
import { TTicket, TTicketReply } from '@/types/admin/support-ticket-type';
import { zodResolver } from '@hookform/resolvers/zod';
import { usePage } from '@inertiajs/react';
import {
  ArrowLeftIcon,
  ChatCircleSlashIcon,
  ChatsCircleIcon,
  PaperclipIcon,
  PaperPlaneTiltIcon,
  XIcon,
} from '@phosphor-icons/react';
import dayjs from 'dayjs';
import { useCallback, useRef, useState, useTransition } from 'react';
import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import z from 'zod';

const ReplySchema = z
  .object({
    message: z.string(),
    attachments: z.array(z.instanceof(File)).optional(),
  })
  .refine(
    (data) =>
      data.message.trim().length > 0 ||
      (data.attachments && data.attachments.length > 0),
    { message: 'Message or attachment is required', path: ['message'] },
  );

type ReplyForm = z.infer<typeof ReplySchema>;

const handleVariant = (status: string) => {
  switch (status) {
    case 'open':
    case 'low':
      return 'successOutline';
    case 'closed':
    case 'high':
      return 'destructiveOutline';
    case 'pending':
    case 'medium':
      return 'warningOutline';
    default:
      return 'outline';
  }
};

interface ChatBoxProps {
  ticketId: number | null;
  onBack: () => void;
  onRefreshList: () => void;
}

export default function ChatBox({
  ticketId,
  onBack,
  onRefreshList,
}: ChatBoxProps) {
  const [attachments, setAttachments] = useState<File[]>([]);
  const [isReplying, startReplying] = useTransition();
  const [isClosing, startClosing] = useTransition();
  const messagesEndRef = useRef<HTMLDivElement>(null);

  const { auth } = usePage<SharedData>().props;
  const currentUser = auth.user;
  const { t } = useTranslation();

  const {
    data: ticketData,
    isLoading,
    mutate: refreshTicket,
  } = useApiSWR(ticketId ? `/user/tickets/${ticketId}` : '');
  const ticket = ticketData as TTicket | undefined;

  const form = useForm<ReplyForm>({
    resolver: zodResolver(ReplySchema),
    defaultValues: { message: '', attachments: [] },
  });

  const handleReply = useCallback(
    (data: ReplyForm) => {
      if (!ticketId) return;
      startReplying(async () => {
        const res = await sendUserTicketReply({
          id: ticketId,
          message: data.message.trim(),
          attachments: attachments.length > 0 ? attachments : undefined,
        });

        if (res?.success) {
          toast.success(t(res.message));
          form.reset();
          setAttachments([]);
          const el = document.getElementById(
            'reply-attachments',
          ) as HTMLInputElement;
          if (el) el.value = '';
          refreshTicket();
          onRefreshList();
        }
      });
    },
    [ticketId, attachments, form, refreshTicket, onRefreshList, t],
  );

  const handleClose = useCallback(() => {
    if (!ticketId) return;
    startClosing(async () => {
      const res = await closeTicket(ticketId);
      if (res?.success) {
        toast.success(t(res.message));
        refreshTicket();
        onRefreshList();
      }
    });
  }, [ticketId, refreshTicket, onRefreshList, t]);

  if (isLoading && ticketId) {
    return (
      <div className="flex flex-1 items-center justify-center gap-2">
        <LoaderIcon />
        {t('Loading...')}
      </div>
    );
  }

  if (!ticketId) {
    return (
      <div className="flex h-full flex-col items-center justify-center text-center">
        <ChatsCircleIcon
          weight="fill"
          className="mb-2 size-14 text-black/40 dark:text-white/40"
        />
        <h3 className="mb-1 text-xl font-medium">
          {t('No conversation selected')}
        </h3>
        <p className="text-sm text-black/50 dark:text-white/50">
          {t('Choose a conversation from the list to continue')}
        </p>
      </div>
    );
  }

  return (
    <>
      <div className="flex flex-wrap items-center justify-between gap-2 bg-[rgba(255,255,255,0.1)] px-4 py-4 sm:px-6">
        <div className="flex items-center gap-3">
          <button
            type="button"
            className="flex size-8 shrink-0 items-center justify-center rounded-full hover:bg-black/10 lg:hidden dark:hover:bg-white/10"
            onClick={onBack}
            aria-label={t('Back to tickets')}
          >
            <ArrowLeftIcon weight="bold" size={18} />
          </button>
          <div>
            <div className="flex flex-wrap items-center gap-2">
              <p className="font-medium">
                {ticket?.subject}
                {' #'}
                {ticket?.id}
              </p>
              <Badge
                variant={handleVariant(ticket?.status ?? '')}
                className="uppercase"
              >
                {ticket?.status}
              </Badge>
            </div>
            <p className="text-sm text-black/50 dark:text-white/50">
              {dayjs(ticket?.created_at).format('h:mm A, MMM D, YYYY')}
            </p>
          </div>
        </div>

        {ticket?.status !== 'closed' && (
          <Button
            variant="secondary"
            className="justify-between rounded-full has-[>svg]:px-4"
            loading={isClosing}
            disabled={isClosing}
            onClick={handleClose}
          >
            <ChatCircleSlashIcon weight="fill" />
            <span>{t('Close this ticket')}</span>
          </Button>
        )}
      </div>

      <div className="flex flex-1 flex-col-reverse space-y-2 overflow-y-auto px-6 py-4">
        {ticket?.ticket_replies?.toReversed()?.map((reply: TTicketReply) => {
          const isCurrentUser = reply.user?.id === currentUser?.id;
          return (
            <div
              key={reply.id}
              className={`flex flex-col ${isCurrentUser ? 'items-end' : 'items-start'}`}
            >
              <div className="max-w-[70%] rounded-2xl bg-white/10 p-4 text-black dark:text-white">
                <p className="text-sm">{reply.message}</p>
                <p className="mt-2 text-xs text-black dark:text-white/50">
                  {dayjs(reply.created_at).format('h:mm A, MMM D, YYYY')}
                </p>
              </div>
              {reply.ticket_attachments?.length > 0 && (
                <div className="mt-1 flex flex-col gap-1">
                  {reply.ticket_attachments.map(
                    (attachment: { id: number; file: string }) => (
                      <img
                        key={attachment.id}
                        src={attachment.file}
                        alt={t('Attached image')}
                        className="max-w-[300px] rounded-lg"
                      />
                    ),
                  )}
                </div>
              )}
            </div>
          );
        })}
        <div ref={messagesEndRef} />
      </div>

      {ticket?.status !== 'closed' ? (
        <Form {...form}>
          <form
            onSubmit={form.handleSubmit(handleReply)}
            className="space-y-3 px-6 py-4"
          >
            <FormField
              control={form.control}
              name="message"
              render={({ field }) => (
                <FormItem>
                  <FormControl>
                    <Textarea
                      placeholder={t('Write your message here...')}
                      className="min-h-20 resize-none rounded-2xl bg-white/10 dark:bg-white/10"
                      {...field}
                    />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <div className="flex flex-wrap items-start justify-between gap-2">
              <div className="flex flex-wrap items-start gap-2">
                {attachments.map((file, index) => (
                  <span
                    key={`${file.name}-${index}`}
                    className="inline-flex items-center gap-1 rounded-md bg-black/5 px-2 py-1 text-xs dark:bg-white/10"
                  >
                    {file.name}
                    <button
                      type="button"
                      onClick={() =>
                        setAttachments((prev) =>
                          prev.filter((_, i) => i !== index),
                        )
                      }
                      className="ml-1 cursor-pointer rounded hover:bg-black/10"
                      aria-label={t('Remove file')}
                    >
                      <XIcon />
                    </button>
                  </span>
                ))}
              </div>
              <div className="flex shrink-0 justify-end gap-2">
                <Input
                  type="file"
                  multiple
                  onChange={(e) => {
                    if (e.target.files?.length) {
                      setAttachments((prev) => [
                        ...prev,
                        ...Array.from(e.target.files!),
                      ]);
                    }
                  }}
                  className="hidden"
                  id="reply-attachments"
                />
                <Button
                  type="button"
                  variant="secondary"
                  className="w-full justify-between rounded-full has-[>svg]:px-4"
                  onClick={() =>
                    document.getElementById('reply-attachments')?.click()
                  }
                >
                  <PaperclipIcon size={16} />
                  <span>{t('Attach File')}</span>
                </Button>
                <Button
                  type="submit"
                  variant="primary"
                  loading={isReplying}
                  className="px-8"
                  disabled={isReplying}
                >
                  <span>{t('Send')}</span>
                  <PaperPlaneTiltIcon weight="fill" />
                </Button>
              </div>
            </div>
          </form>
        </Form>
      ) : (
        <p className="py-6 text-center text-sm text-black/40 dark:text-white/40">
          {t(
            'This ticket is closed. Open a new ticket if you need further help.',
          )}
        </p>
      )}
    </>
  );
}
