'use client';

import {useEffect, useRef, useState, type SubmitEvent} from 'react';
import {useRouter, useSearchParams} from 'next/navigation';
import {ArrowLeft, ArrowRight, CheckCheck, ChevronLeft, ChevronRight, CircleHelp, Clock3, Headphones, History, Inbox, LoaderCircle, LockKeyhole, MessageSquareText, Plus, RefreshCw, Search, Send, ShieldCheck, Ticket, X} from 'lucide-react';
import {useSite} from './site-shell';
import {useTicketResource} from './use-ticket-resource';
import {ticketReplyAttempt, type TicketReplyAttempt} from '@/lib/ticket-retry';
import {TICKET_DEPARTMENTS, TICKET_PRIORITIES, TICKET_STATUSES, type TicketDepartment, type TicketPriority, type TicketStatus, type SupportTicket, type TicketDetail, type TicketEvent, type TicketList} from '@/lib/support-tickets';

const number = (value: number) => value.toLocaleString('fa-IR');
function date(value: string) {
  const parsed = new Date(value);
  return Number.isNaN(parsed.getTime()) ? '—' : new Intl.DateTimeFormat('fa-IR', {dateStyle: 'medium', timeStyle: 'short'}).format(parsed);
}
const entries = <T extends Record<string, string>>(options: T) => Object.entries(options) as [keyof T & string, string][];

class TicketRequestError extends Error {
  constructor(message: string, readonly status: number, readonly code?: string) {super(message);}
}

async function submitTicket(payload: Record<string, unknown>, signal: AbortSignal): Promise<TicketDetail> {
  const response = await fetch('/api/tickets', {method: 'POST', headers: {'Content-Type': 'application/json'}, credentials: 'same-origin', body: JSON.stringify(payload), signal});
  const result = await response.json();
  if (!response.ok) {
    if (response.status === 401 && !signal.aborted) window.dispatchEvent(new Event('planck:session-refresh'));
    const message = result && typeof result === 'object' && 'error' in result && typeof result.error === 'string' ? result.error : 'ارسال انجام نشد. لطفاً دوباره تلاش کنید.';
    const code = result && typeof result === 'object' && 'code' in result && typeof result.code === 'string' ? result.code : undefined;
    throw new TicketRequestError(message, response.status, code);
  }
  return result as TicketDetail;
}

function TicketStatusBadge({status}: {status: TicketStatus}) {
  return <span className={`ticket-status ticket-status-${status}`}><i aria-hidden="true"/>{TICKET_STATUSES[status]}</span>;
}

function TicketLoading() {
  return <section className="dash-card ticket-loading" aria-busy="true" aria-label="در حال دریافت تیکت‌ها"><div className="ticket-loading-line"/><div className="ticket-skeleton-heading"/><div className="ticket-skeleton-row"/><div className="ticket-skeleton-row"/><div className="ticket-skeleton-row"/><output className="ticket-loading-caption"><LoaderCircle size={15}/>در حال آماده‌سازی گفتگوها</output></section>;
}

function TicketError({message, retry}: {message: string; retry?: () => void}) {
  return <div className="ticket-error" role="alert"><span>{message}</span>{retry && <button type="button" onClick={retry}><RefreshCw size={15}/>تلاش دوباره</button>}</div>;
}

export function CustomerTickets() {
  const {user, sessionStatus, openTickets} = useSite();
  if (!user && sessionStatus === 'loading') return <TicketLoading/>;
  if (!user) return <section className="dash-card tickets-guest" dir="rtl"><span className="tickets-guest-icon"><LockKeyhole size={28}/></span><span className="tickets-eyebrow">پشتیبانی اختصاصی پلانک</span><h2>برای ارسال و پیگیری تیکت وارد حساب شوید</h2><p>هنوز وارد حساب خود نشده‌اید. پس از ورود، می‌توانید درخواستتان را برای واحد مربوط ارسال کنید و پاسخ‌ها و روند رسیدگی را در همین صفحه ببینید.</p><button type="button" className="dash-primary" onClick={openTickets}>ورود به حساب و ادامه<ArrowLeft size={18}/></button><small><ShieldCheck size={15}/>گفتگوهای شما در حساب شخصی‌تان نگهداری می‌شود.</small></section>;
  return <TicketWorkspace key={user.id}/>;
}

function TicketWorkspace() {
  const router = useRouter(), params = useSearchParams();
  const selected = params.get('ticket');
  const [creating, setCreating] = useState(false), [notice, setNotice] = useState('');
  const openTicket = (id: string) => {setCreating(false); router.push(`/account/tickets?ticket=${encodeURIComponent(id)}`, {scroll: false});};
  const back = () => {setCreating(false); setNotice(''); router.push('/account/tickets', {scroll: false});};
  return <div className="customer-tickets" dir="rtl" lang="fa">
    {notice && <output className="ticket-success"><CheckCheck size={19}/><span>{notice}</span><button type="button" onClick={() => setNotice('')} aria-label="بستن پیام"><X size={16}/></button></output>}
    {creating ? <CreateTicket onCancel={() => setCreating(false)} onCreated={detail => {setNotice(`تیکت شماره ${number(detail.ticket.number)} ثبت و برای ${TICKET_DEPARTMENTS[detail.ticket.department]} ارسال شد.`); openTicket(detail.ticket.id);}}/>
      : selected ? <TicketConversation key={selected} id={selected} onBack={back} onCreate={() => {setNotice(''); setCreating(true);}}/>
      : <CustomerTicketList onOpen={openTicket} onCreate={() => {setNotice(''); setCreating(true);}}/>}
  </div>;
}

function CustomerTicketList({onOpen, onCreate}: {onOpen: (id: string) => void; onCreate: () => void}) {
  const [search, setSearch] = useState(''), [query, setQuery] = useState('');
  const [department, setDepartment] = useState<TicketDepartment | ''>(''), [status, setStatus] = useState<TicketStatus | ''>(''), [priority, setPriority] = useState<TicketPriority | ''>(''), [page, setPage] = useState(1);
  useEffect(() => {const timer = setTimeout(() => {setQuery(search.trim()); setPage(1);}, 300); return () => clearTimeout(timer);}, [search]);
  const parameters = new URLSearchParams({page: String(page), page_size: '20'});
  if (query) parameters.set('q', query);
  if (department) parameters.set('department', department);
  if (status) parameters.set('status', status);
  if (priority) parameters.set('priority', priority);
  const resource = useTicketResource<TicketList>(`/api/tickets?${parameters}`);
  const data = resource.data, filtered = !!(query || department || status || priority);
  const clearFilters = () => {setSearch(''); setQuery(''); setDepartment(''); setStatus(''); setPriority(''); setPage(1);};
  const pages = data ? Math.max(1, Math.ceil(data.total / data.page_size)) : 1;
  return <>
    <section className="dash-card tickets-intro"><div className="tickets-intro-copy"><span className="tickets-feature-icon"><Headphones size={25}/></span><div><span className="tickets-eyebrow">یک مسیر روشن برای پاسخ شما</span><h2>گفتگو با تیم پشتیبانی</h2><p>موضوع را انتخاب کنید؛ پیام شما به واحد مربوط می‌رسد و روند رسیدگی همین‌جا قابل پیگیری است.</p></div></div><button type="button" className="dash-primary" onClick={onCreate}><Plus size={19}/>تیکت جدید</button></section>
    <section className="dash-card tickets-list-panel">
      <div className="tickets-list-heading"><div><h2><MessageSquareText size={20}/>درخواست‌های شما</h2><span>{data ? `${number(data.total)} تیکت${filtered ? ' با این فیلترها' : ' ثبت‌شده'}` : 'گفتگوها و پاسخ‌های پشتیبانی'}</span></div><button type="button" className="dash-secondary" onClick={() => void resource.reload()} disabled={resource.loading} aria-label="تازه‌سازی فهرست تیکت‌ها"><RefreshCw size={17} className={resource.loading ? 'ticket-spin' : ''}/><span>تازه‌سازی</span></button></div>
      <div className="tickets-filters">
        <label className="ticket-search"><Search size={18}/><input aria-label="جست‌وجوی عنوان تیکت" placeholder="جست‌وجو در عنوان تیکت‌ها" value={search} maxLength={160} onChange={event => setSearch(event.target.value)}/></label>
        <label><span>وضعیت</span><select value={status} onChange={event => {setStatus(event.target.value as TicketStatus | ''); setPage(1);}}><option value="">همه وضعیت‌ها</option>{entries(TICKET_STATUSES).map(([value, label]) => <option key={value} value={value}>{label}</option>)}</select></label>
        <label><span>واحد پاسخ‌گو</span><select value={department} onChange={event => {setDepartment(event.target.value as TicketDepartment | ''); setPage(1);}}><option value="">همه واحدها</option>{entries(TICKET_DEPARTMENTS).map(([value, label]) => <option key={value} value={value}>{label}</option>)}</select></label>
        <label><span>اولویت</span><select value={priority} onChange={event => {setPriority(event.target.value as TicketPriority | ''); setPage(1);}}><option value="">همه اولویت‌ها</option>{entries(TICKET_PRIORITIES).map(([value, label]) => <option key={value} value={value}>{label}</option>)}</select></label>
      </div>
      {resource.error && <TicketError message={resource.error} retry={() => void resource.reload()}/>}
      {resource.loading && !data ? <TicketLoading/> : data && data.items.length ? <div className="ticket-records" aria-label="فهرست تیکت‌ها">{data.items.map(ticket => <TicketRow key={ticket.id} ticket={ticket} onOpen={() => onOpen(ticket.id)}/>)}</div> : data && <div className="tickets-empty"><span><Inbox size={32}/></span><h3>{filtered ? 'تیکتی با این مشخصات پیدا نشد' : 'اولین گفتگوی شما از اینجا شروع می‌شود'}</h3><p>{filtered ? 'عنوان یا فیلترها را تغییر دهید تا درخواست موردنظر را پیدا کنید.' : 'سؤال یا درخواستتان را بنویسید؛ پاسخ تیم پشتیبانی در همین صفحه ثبت می‌شود.'}</p><button type="button" className="dash-secondary" onClick={filtered ? clearFilters : onCreate}>{filtered ? 'پاک کردن فیلترها' : 'ارسال اولین تیکت'}<ArrowLeft size={16}/></button></div>}
      {!!data?.total && <nav className="tickets-pagination" aria-label="صفحه‌بندی تیکت‌ها"><span>صفحه {number(page)} از {number(pages)}</span><div><button type="button" className="dash-secondary" disabled={page <= 1 || resource.loading} onClick={() => setPage(value => value - 1)}><ChevronRight size={17}/>قبلی</button><button type="button" className="dash-secondary" disabled={page >= pages || resource.loading} onClick={() => setPage(value => value + 1)}>بعدی<ChevronLeft size={17}/></button></div></nav>}
    </section>
  </>;
}

function TicketRow({ticket, onOpen}: {ticket: SupportTicket; onOpen: () => void}) {
  return <button type="button" className="ticket-record" onClick={onOpen}><span className="ticket-record-icon"><Ticket size={20}/></span><div className="ticket-record-copy"><div className="ticket-record-title"><strong>{ticket.subject}</strong><TicketStatusBadge status={ticket.status}/></div><div className="ticket-record-meta"><span>#{number(ticket.number)}</span><span>{TICKET_DEPARTMENTS[ticket.department]}</span><span className={`ticket-priority ticket-priority-${ticket.priority}`}>اولویت {TICKET_PRIORITIES[ticket.priority]}</span></div></div><div className="ticket-record-date"><span>آخرین به‌روزرسانی</span><time dateTime={ticket.updated_at}>{date(ticket.updated_at)}</time></div><ChevronLeft size={18}/></button>;
}

function CreateTicket({onCancel, onCreated}: {onCancel: () => void; onCreated: (detail: TicketDetail) => void}) {
  const [subject, setSubject] = useState(''), [body, setBody] = useState('');
  const [department, setDepartment] = useState<TicketDepartment>('general'), [priority, setPriority] = useState<TicketPriority>('normal');
  const [error, setError] = useState(''), [sending, setSending] = useState(false);
  const request = useRef<AbortController | null>(null), identity = useRef({payload: '', id: ''});
  const subjectInput = useRef<HTMLInputElement>(null);
  useEffect(() => {subjectInput.current?.focus(); return () => request.current?.abort();}, []);
  async function submit(event: SubmitEvent<HTMLFormElement>) {
    event.preventDefault();
    if (request.current) return;
    if (subject.trim().length < 5 || body.trim().length < 5) {setError('عنوان و توضیحات را با حداقل ۵ نویسه کامل کنید.'); return;}
    const payload = {action: 'create', subject: subject.trim(), department, priority, body: body.trim()};
    const signature = JSON.stringify(payload);
    if (identity.current.payload !== signature) identity.current = {payload: signature, id: crypto.randomUUID()};
    const current = new AbortController(); request.current = current;
    setError(''); setSending(true);
    try {const result = await submitTicket({...payload, client_id: identity.current.id}, current.signal); if (!current.signal.aborted) onCreated(result);}
    catch (failure) {if (!current.signal.aborted) setError(failure instanceof TicketRequestError ? failure.message : 'ارتباط برقرار نشد. متن شما حفظ شده است؛ دوباره ارسال کنید.');}
    finally {if (!current.signal.aborted) {request.current = null; setSending(false);}}
  }
  return <section className="dash-card ticket-compose"><div className="tickets-form-heading"><div><span className="tickets-eyebrow">پشتیبانی شخصی شما</span><h2>ارسال تیکت جدید</h2><p>واحد مرتبط را انتخاب کنید و درخواستتان را با جزئیات بنویسید.</p></div><button type="button" className="dash-secondary" onClick={onCancel} disabled={sending}><ArrowRight size={17}/>بازگشت</button></div>
    <form onSubmit={event => void submit(event)} className="ticket-form">
      <label htmlFor="ticket-subject"><span>عنوان درخواست <small>الزامی</small></span><input id="ticket-subject" ref={subjectInput} value={subject} onChange={event => setSubject(event.target.value)} placeholder="مثلاً: بررسی وضعیت واریز به کیف پول" required minLength={5} maxLength={160} disabled={sending}/></label>
      <label htmlFor="ticket-department"><span>واحد پاسخ‌گو</span><select id="ticket-department" value={department} onChange={event => setDepartment(event.target.value as TicketDepartment)} disabled={sending}>{entries(TICKET_DEPARTMENTS).map(([value, label]) => <option key={value} value={value}>{label}</option>)}</select><small>اگر از واحد مربوط مطمئن نیستید، پشتیبانی عمومی را انتخاب کنید.</small></label>
      <fieldset className="ticket-priority-options" disabled={sending}><legend>اولویت درخواست</legend><div>{entries(TICKET_PRIORITIES).map(([value, label]) => <label key={value} aria-label={label} className={`ticket-priority-choice priority-choice-${value}${priority === value ? ' is-selected' : ''}`}><input type="radio" name="ticket-priority" value={value} checked={priority === value} onChange={() => setPriority(value)}/><span><strong>{label}</strong><small>{value === 'normal' ? 'پرسش و راهنمایی' : value === 'high' ? 'اختلال در استفاده از خدمات' : 'موضوع فوری یا امنیتی'}</small></span></label>)}</div></fieldset>
      <label htmlFor="ticket-body"><span>شرح درخواست <small>الزامی</small></span><textarea id="ticket-body" rows={8} value={body} onChange={event => setBody(event.target.value)} placeholder="موضوع، زمان رخداد و مراحل انجام‌شده را شرح دهید تا بهتر راهنمایی‌تان کنیم." required minLength={5} maxLength={6000} disabled={sending}/><small className="ticket-character-count">{number(body.length)} از {number(6000)} نویسه</small></label>
      <p className="ticket-privacy"><ShieldCheck size={18}/>رمز عبور، کد ورود، کلید خصوصی یا عبارت بازیابی والت را در تیکت ارسال نکنید.</p>
      {error && <TicketError message={error}/>}
      <div className="ticket-form-actions"><span><CircleHelp size={16}/>پاسخ و تغییر وضعیت را در تیکت و اعلان‌های حساب دنبال کنید.</span><button type="submit" className="dash-primary" disabled={sending}>{sending ? <LoaderCircle size={18} className="ticket-spin"/> : <Send size={18}/>} {sending ? 'در حال ارسال…' : 'ثبت و ارسال تیکت'}</button></div>
    </form>
  </section>;
}

function TicketConversation({id, onBack, onCreate}: {id: string; onBack: () => void; onCreate: () => void}) {
  const valid = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id);
  const resource = useTicketResource<TicketDetail>(valid ? `/api/tickets?id=${encodeURIComponent(id)}` : null);
  const [reply, setReply] = useState(''), [error, setError] = useState(''), [sending, setSending] = useState(false), [sent, setSent] = useState(false);
  const request = useRef<AbortController | null>(null), identity = useRef<TicketReplyAttempt | null>(null);
  useEffect(() => () => request.current?.abort(), []);
  async function sendReply(event: SubmitEvent<HTMLFormElement>) {
    event.preventDefault();
    if (request.current || !resource.data) return;
    if (reply.trim().length < 5) {setError('لطفاً پاسخ خود را با حداقل ۵ نویسه بنویسید.'); return;}
    const attempt = ticketReplyAttempt(identity.current, reply, resource.data.ticket.version);
    identity.current = attempt;
    const current = new AbortController(); request.current = current;
    setError(''); setSent(false); setSending(true);
    try {
      const detail = await submitTicket({action: 'reply', id, version: attempt.version, body: attempt.body, client_id: attempt.clientId}, current.signal);
      if (!current.signal.aborted) {resource.replace(latest => latest && latest.ticket.version > detail.ticket.version ? latest : detail); setReply(''); identity.current = null; setSent(true);}
    } catch (failure) {
      if (!current.signal.aborted) {
        if (failure instanceof TicketRequestError && failure.code === 'ticket_version_conflict') {identity.current = null; await resource.reload(); setError('تیکت به‌روزرسانی شده است. آخرین پیام‌ها را ببینید و پاسخ خود را دوباره ارسال کنید.');}
        else if (failure instanceof TicketRequestError && failure.code === 'ticket_closed') {await resource.reload(); setError(failure.message);}
        else setError(failure instanceof TicketRequestError ? failure.message : 'ارسال انجام نشد. پاسخ شما حفظ شده است؛ دوباره تلاش کنید.');
      }
    } finally {if (!current.signal.aborted) {request.current = null; setSending(false);}}
  }
  const detail = resource.data;
  return <>
    <div className="tickets-conversation-toolbar"><button type="button" className="dash-secondary" onClick={onBack} disabled={sending}><ArrowRight size={17}/>همه تیکت‌ها</button><button type="button" className="dash-secondary" onClick={() => void resource.reload()} disabled={!valid || resource.loading || sending}><RefreshCw size={16} className={resource.loading ? 'ticket-spin' : ''}/>تازه‌سازی</button></div>
    {!valid ? <TicketError message="نشانی تیکت معتبر نیست. از فهرست تیکت‌ها درخواست خود را انتخاب کنید."/> : resource.error && <TicketError message={resource.error} retry={() => void resource.reload()}/>}
    {resource.loading && !detail ? <TicketLoading/> : detail && <>
      <section className="dash-card ticket-detail-heading"><div><span className="tickets-eyebrow">تیکت #{number(detail.ticket.number)}</span><h2>{detail.ticket.subject}</h2><TicketStatusBadge status={detail.ticket.status}/></div><dl><div><dt>واحد پاسخ‌گو</dt><dd>{TICKET_DEPARTMENTS[detail.ticket.department]}</dd></div><div><dt>اولویت</dt><dd className={`ticket-priority ticket-priority-${detail.ticket.priority}`}>{TICKET_PRIORITIES[detail.ticket.priority]}</dd></div><div><dt>تاریخ ثبت</dt><dd><time dateTime={detail.ticket.created_at}>{date(detail.ticket.created_at)}</time></dd></div><div><dt>آخرین به‌روزرسانی</dt><dd><time dateTime={detail.ticket.updated_at}>{date(detail.ticket.updated_at)}</time></dd></div></dl></section>
      <section className="dash-card ticket-conversation"><h2><MessageSquareText size={20}/>گفتگو و پاسخ‌ها<span>{number(detail.messages.length)} پیام</span></h2><div className="ticket-messages">{detail.messages.map(message => <article key={message.id} className={`ticket-message ticket-message-${message.author_kind}`}><header><span className="ticket-message-avatar">{message.author_kind === 'admin' ? <Headphones size={19}/> : <MessageSquareText size={18}/>}</span><div><strong>{message.author_kind === 'admin' ? message.author_name || 'تیم پشتیبانی پلانک' : 'شما'}</strong><span>{message.author_kind === 'admin' ? 'پشتیبانی پلانک' : 'صاحب حساب'}</span></div><time dateTime={message.created_at}>{date(message.created_at)}</time></header><p>{message.body}</p></article>)}</div>
        {detail.ticket.status === 'closed' ? <div className="ticket-closed"><LockKeyhole size={20}/><div><strong>این گفتگو بسته شده است</strong><p>برای موضوع جدید می‌توانید تیکت دیگری ثبت کنید. تاریخچه این گفتگو همچنان در دسترس شماست.</p></div><button type="button" className="dash-secondary" onClick={onCreate}>تیکت جدید<Plus size={16}/></button></div> : <form className="ticket-form ticket-reply" onSubmit={event => void sendReply(event)}><label htmlFor="ticket-reply"><span>پاسخ شما</span><textarea id="ticket-reply" rows={5} value={reply} onChange={event => {setReply(event.target.value); setSent(false);}} placeholder="پاسخ یا اطلاعات تکمیلی خود را بنویسید…" minLength={5} maxLength={6000} required disabled={sending}/><small className="ticket-character-count">{number(reply.length)} از {number(6000)} نویسه</small></label>{detail.ticket.status === 'resolved' && <p className="ticket-reopen-hint"><MessageSquareText size={16}/>با ارسال پاسخ، این تیکت دوباره برای بررسی باز می‌شود.</p>}{error && <TicketError message={error}/>}<div className="ticket-form-actions"><output>{sent ? <><CheckCheck size={17}/>پاسخ شما ثبت شد.</> : <><ShieldCheck size={16}/>اطلاعات محرمانه ورود یا والت را ارسال نکنید.</>}</output><button type="submit" className="dash-primary" disabled={sending}>{sending ? <LoaderCircle className="ticket-spin" size={18}/> : <Send size={18}/>} {sending ? 'در حال ارسال…' : 'ارسال پاسخ'}</button></div></form>}
      </section>
      <details className="dash-card ticket-history"><summary><History size={19}/><strong>روند رسیدگی به تیکت</strong><span>{number(detail.events.length)} رویداد</span><ChevronLeft size={17}/></summary><ol>{detail.events.map(event => <li key={event.id}><span><Clock3 size={15}/></span><div><p>{eventTitle(event)}</p><time dateTime={event.created_at}>{date(event.created_at)}</time></div></li>)}</ol></details>
    </>}
  </>;
}

function eventTitle(event: TicketEvent) {
  if (event.event_type === 'created') return `تیکت ثبت و به ${TICKET_DEPARTMENTS[event.to_department]} ارسال شد.`;
  if (event.event_type === 'customer_reply') return event.from_status === 'resolved' ? 'پاسخ شما ثبت شد و تیکت دوباره برای بررسی باز شد.' : 'پاسخ شما به گفتگو اضافه شد.';
  const changes: string[] = [];
  if (event.from_department !== event.to_department) changes.push(`ارجاع به ${TICKET_DEPARTMENTS[event.to_department]}`);
  if (event.from_status !== event.to_status) changes.push(`وضعیت: ${TICKET_STATUSES[event.to_status]}`);
  if (event.from_priority !== event.to_priority) changes.push(`اولویت: ${TICKET_PRIORITIES[event.to_priority]}`);
  return changes.length ? `به‌روزرسانی پشتیبانی — ${changes.join(' · ')}` : 'پاسخ یا بررسی جدید توسط تیم پشتیبانی ثبت شد.';
}
