'use client';
import { ErrorState } from '@/components/ui/feedback/ErrorState';

import { useState, useRef, useEffect } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { HydratedIsland } from '@/components/HydratedIsland';
import { useT } from '@/lib/i18n/react';
import type { Locale } from '@/lib/i18n';
import { getCsrfToken } from '@/lib/csrf';
import { captureCaught } from '@/lib/observability';
import { Button } from '@/components/ui/primitives/Button';
import { Textarea } from '@/components/ui/primitives/Textarea';
import { Spinner } from '@/components/ui/feedback/Spinner';

interface ClientPurchaseMessage {
  id: string;
  senderType: 'USER' | 'VENDOR';
  body: string;
  readAt: string | null;
  createdAt: string;
}

interface PurchaseMessageThreadProps {
  purchaseId: string;
}

export function PurchaseMessageThreadInner({ purchaseId }: PurchaseMessageThreadProps) {
  const tMsg = useT('domain_purchase_message');
  const tCommon = useT('common');
  const tDetail = useT('purchase_detail');
  const qc = useQueryClient();
  const [body, setBody] = useState('');
  const [sendError, setSendError] = useState<string | null>(null);
  const bottomRef = useRef<HTMLDivElement>(null);

  const { data, isLoading, isError, refetch } = useQuery<{ messages: ClientPurchaseMessage[] }>({
    queryKey: ['purchase-messages', purchaseId],
    queryFn: async () => {
      const res = await fetch(`/api/purchases/${purchaseId}/messages`, {
        headers: { 'Cache-Control': 'no-cache' },
      });
      const json = (await res.json()) as { ok: boolean; messages?: ClientPurchaseMessage[] };
      if (!json.ok) throw new Error('fetch-messages-failed');
      return { messages: json.messages ?? [] };
    },
  });

  const sendMutation = useMutation({
    mutationFn: async (messageBody: string) => {
      const res = await fetch(`/api/purchases/${purchaseId}/messages`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-csrf-token': getCsrfToken(),
        },
        body: JSON.stringify({ body: messageBody }),
      });
      const json = (await res.json()) as { ok: boolean };
      if (!json.ok) throw new Error('send-message-failed');
    },
    onSuccess: () => {
      setBody('');
      setSendError(null);
      void qc.invalidateQueries({ queryKey: ['purchase-messages', purchaseId] });
    },
    onError: (err) => {
      captureCaught(err, {
        scope: 'features.purchase-detail.PurchaseMessageThread.send',
        severity: 'warning',
      });
      setSendError(tMsg('sendError'));
    },
  });

  useEffect(() => {
    fetch(`/api/purchases/${purchaseId}/messages/read`, {
      method: 'POST',
      headers: { 'x-csrf-token': getCsrfToken() },
    }).catch((err) =>
      captureCaught(err, {
        scope: 'features.purchase-detail.PurchaseMessageThread.markRead',
        severity: 'info',
      }),
    );
  }, [purchaseId]);

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [data?.messages]);

  const messages = data?.messages ?? [];
  const ownRole = 'USER' as const;

  if (isError) {
    return (
      <ErrorState
        title={tCommon('error_loading')}
        action={
          <Button variant="secondary" size="sm" onClick={() => refetch()}>
            {tCommon('retry')}
          </Button>
        }
      />
    );
  }
  return (
    <section aria-label={tDetail('messages_title')} className="mx-auto mt-4 max-w-sm px-4 pb-6">
      <h2 className="text-text-primary mb-3 text-sm font-semibold">{tDetail('messages_title')}</h2>

      <div
        className="border-border-default bg-surface-subtle mb-3 flex max-h-72 flex-col gap-2 overflow-y-auto rounded-xl border p-3"
        role="log"
        aria-live="polite"
        aria-label={tDetail('messages_title')}
      >
        {isLoading && (
          <div className="flex items-center justify-center gap-2 py-6">
            <Spinner size="sm" label={tMsg('loading')} />
            <span className="text-text-muted text-xs">{tMsg('loading')}</span>
          </div>
        )}
        {!isLoading && messages.length === 0 && (
          <div className="flex flex-col items-center gap-1 py-4">
            <p className="text-text-muted text-sm">{tMsg('empty')}</p>
            <p className="text-text-muted text-xs">{tDetail('messages_hint')}</p>
          </div>
        )}
        {messages.map((msg) => {
          const isOwn = msg.senderType === ownRole;
          return (
            <div key={msg.id} className={`flex ${isOwn ? 'justify-end' : 'justify-start'}`}>
              <div
                className={`max-w-[75%] rounded-2xl px-3 py-2 text-sm ${
                  isOwn ? 'bg-brand-primary-600 text-white' : 'bg-surface-raised text-text-primary'
                }`}
              >
                <p className="break-words">{msg.body}</p>
              </div>
            </div>
          );
        })}
        <div ref={bottomRef} />
      </div>

      <div className="flex flex-col gap-2">
        <Textarea
          className="w-full resize-none rounded-xl"
          rows={2}
          placeholder={tMsg('placeholder')}
          value={body}
          onChange={(e) => setBody(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === 'Enter' && !e.shiftKey && body.trim()) {
              e.preventDefault();
              sendMutation.mutate(body.trim());
            }
          }}
          aria-label={tMsg('placeholder')}
          disabled={sendMutation.isPending}
        />
        {sendError && (
          <p role="alert" className="text-danger-600 text-xs">
            {sendError}
          </p>
        )}
        <Button
          variant="primary"
          size="md"
          disabled={!body.trim() || sendMutation.isPending}
          onClick={() => {
            if (body.trim()) sendMutation.mutate(body.trim());
          }}
          className="w-full"
          aria-label={tMsg('send')}
        >
          {tMsg('send')}
        </Button>
      </div>
    </section>
  );
}

export function PurchaseMessageThread({
  purchaseId,
  locale,
}: PurchaseMessageThreadProps & { locale?: Locale }) {
  return (
    <HydratedIsland locale={locale}>
      <PurchaseMessageThreadInner purchaseId={purchaseId} />
    </HydratedIsland>
  );
}
