'use client';

import Link from 'next/link';
import { useMemo, useState } from 'react';
import { useMutation, useQuery, useSuspenseQuery } from '@tanstack/react-query';
import { toast } from 'sonner';
import { Icons } from '@/components/icons';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { formatDate, formatDateTime } from '@/lib/date-format';
import { formatNumber } from '@/lib/number-format';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue
} from '@/components/ui/select';
import {
  CrmCurrencyInput,
  CrmDateInput,
  CrmTextarea
} from '@/features/crm/components/crm-form-controls';
import {
  invalidateOpportunityMutationQueries,
  markOpportunityLostMutation,
  markOpportunityWonMutation,
  reopenOpportunityMutation
} from '../api/mutations';
import { opportunityAttachmentsOptions, opportunityByIdOptions } from '../api/queries';
import type { OpportunityReferenceData } from '../api/types';

function FieldItem({ label, value }: { label: string; value: string | null | undefined }) {
  return (
    <div className='space-y-1'>
      <div className='text-muted-foreground text-xs'>{label}</div>
      <div className='text-sm'>{value || '-'}</div>
    </div>
  );
}

function getOutcomeLabel(stage: string) {
  if (stage === 'closed_won') return 'Won';
  if (stage === 'closed_lost') return 'Lost';
  return 'Open';
}

type OpportunityOutcomeCardProps = {
  opportunityId: string;
  referenceData: OpportunityReferenceData;
  canViewCommercialData: boolean;
  canMarkWon: boolean;
  canMarkLost: boolean;
  canReopen: boolean;
};

export function OpportunityOutcomeCard({
  opportunityId,
  referenceData,
  canViewCommercialData,
  canMarkWon,
  canMarkLost,
  canReopen
}: OpportunityOutcomeCardProps) {
  const { data } = useSuspenseQuery(opportunityByIdOptions(opportunityId));
  const attachmentsQuery = useQuery({
    ...opportunityAttachmentsOptions(opportunityId),
    enabled: canViewCommercialData
  });
  const opportunity = data.opportunity;
  const [wonOpen, setWonOpen] = useState(false);
  const [lostOpen, setLostOpen] = useState(false);
  const [reopenOpen, setReopenOpen] = useState(false);
  const [poNumber, setPoNumber] = useState('');
  const [poDate, setPoDate] = useState('');
  const [poAmount, setPoAmount] = useState('');
  const [poCurrency, setPoCurrency] = useState('THB');
  const [wonRemark, setWonRemark] = useState('');
  const [lostReason, setLostReason] = useState('');
  const [lostCompetitor, setLostCompetitor] = useState('');
  const [lostRemark, setLostRemark] = useState('');
  const [reopenReason, setReopenReason] = useState('');
  const [poFile, setPoFile] = useState<File | null>(null);
  const [poFileDescription, setPoFileDescription] = useState('');

  const wonMutation = useMutation({
    ...markOpportunityWonMutation,
    onSuccess: async () => {
      toast.success('Marked opportunity as won');
      setWonOpen(false);
      await invalidateOpportunityMutationQueries(opportunityId);
    },
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Failed to mark won')
  });
  const lostMutation = useMutation({
    ...markOpportunityLostMutation,
    onSuccess: async () => {
      toast.success('Marked opportunity as lost');
      setLostOpen(false);
      await invalidateOpportunityMutationQueries(opportunityId);
    },
    onError: (error) => toast.error(error instanceof Error ? error.message : 'Failed to mark lost')
  });
  const reopenMutation = useMutation({
    ...reopenOpportunityMutation,
    onSuccess: async () => {
      toast.success('Reopened opportunity');
      setReopenOpen(false);
      await invalidateOpportunityMutationQueries(opportunityId);
    },
    onError: (error) =>
      toast.error(error instanceof Error ? error.message : 'Failed to reopen opportunity')
  });
  const uploadMutation = useMutation({
    mutationFn: async () => {
      if (!poFile) {
        throw new Error('Please choose a PO attachment file');
      }

      const formData = new FormData();
      formData.append('file', poFile);
      formData.append('description', poFileDescription);
      const response = await fetch(`/api/crm/opportunities/${opportunityId}/po-attachments`, {
        method: 'POST',
        body: formData
      });

      if (!response.ok) {
        const payload = (await response.json().catch(() => null)) as { message?: string } | null;
        throw new Error(payload?.message ?? 'Failed to upload PO attachment');
      }

      return response.json();
    },
    onSuccess: async () => {
      toast.success('PO attachment uploaded');
      setPoFile(null);
      setPoFileDescription('');
      await invalidateOpportunityMutationQueries(opportunityId);
    },
    onError: (error) =>
      toast.error(error instanceof Error ? error.message : 'Failed to upload PO attachment')
  });

  const closedDate = opportunity.closedWonAt ?? opportunity.closedLostAt;
  const lostReasonLabel = useMemo(() => {
    if (!opportunity.lostReason) {
      return null;
    }

    return (
      opportunity.lostReasonLabel ??
      referenceData.lostReasons.find(
        (item) => item.id === opportunity.lostReason || item.code === opportunity.lostReason
      )?.label ??
      opportunity.lostReason
    );
  }, [opportunity.lostReason, opportunity.lostReasonLabel, referenceData.lostReasons]);
  const attachmentItems = attachmentsQuery.data?.items ?? [];

  return (
    <>
      <Card>
        <CardHeader>
          <CardTitle>Outcome</CardTitle>
          <CardDescription>
            Official won/lost lifecycle and purchase order tracking.
          </CardDescription>
        </CardHeader>
        <CardContent className='space-y-4'>
          <div className='flex items-center justify-between gap-3'>
            <Badge
              variant={
                opportunity.pipelineStage === 'closed_won'
                  ? 'default'
                  : opportunity.pipelineStage === 'closed_lost'
                    ? 'destructive'
                    : 'secondary'
              }
            >
              {getOutcomeLabel(opportunity.pipelineStage)}
            </Badge>
            <div className='flex flex-wrap gap-2'>
              {opportunity.pipelineStage === 'opportunity' && canMarkWon ? (
                <Button
                  size='sm'
                  onClick={() => {
                    setPoNumber(opportunity.poNumber ?? '');
                    setPoDate(opportunity.poDate ? opportunity.poDate.slice(0, 10) : '');
                    setPoAmount(
                      opportunity.poAmount !== null && opportunity.poAmount !== undefined
                        ? String(opportunity.poAmount)
                        : ''
                    );
                    setPoCurrency(opportunity.poCurrency ?? 'THB');
                    setWonRemark('');
                    setWonOpen(true);
                  }}
                >
                  <Icons.check className='mr-2 h-4 w-4' />
                  Mark Won
                </Button>
              ) : null}
              {opportunity.pipelineStage === 'opportunity' && canMarkLost ? (
                <Button
                  variant='destructive'
                  size='sm'
                  onClick={() => {
                    setLostReason(opportunity.lostReason ?? '');
                    setLostCompetitor(opportunity.lostCompetitor ?? '');
                    setLostRemark(opportunity.lostRemark ?? '');
                    setLostOpen(true);
                  }}
                >
                  <Icons.xCircle className='mr-2 h-4 w-4' />
                  Mark Lost
                </Button>
              ) : null}
              {opportunity.pipelineStage === 'closed_lost' && canReopen ? (
                <Button variant='outline' size='sm' onClick={() => setReopenOpen(true)}>
                  Reopen
                </Button>
              ) : null}
            </div>
          </div>

          <div className='grid gap-4 md:grid-cols-2'>
            <FieldItem label='Closed By' value={opportunity.closedByName} />
            <FieldItem
              label='Closed Date'
              value={closedDate ? formatDateTime(closedDate) : null}
            />
            <FieldItem label='PO Number' value={opportunity.poNumber} />
            <FieldItem
              label='PO Date'
              value={opportunity.poDate ? formatDate(opportunity.poDate) : null}
            />
            <FieldItem
              label='PO Amount'
              value={
                canViewCommercialData && opportunity.poAmount !== null
                  ? `${formatNumber(opportunity.poAmount)} ${opportunity.poCurrency ?? ''}`.trim()
                  : canViewCommercialData
                    ? null
                    : 'Restricted'
              }
            />
            <FieldItem label='Lost Reason' value={lostReasonLabel} />
            <FieldItem label='Lost Competitor' value={opportunity.lostCompetitor} />
            <FieldItem label='Remark' value={opportunity.lostRemark} />
          </div>

          {canViewCommercialData && opportunity.pipelineStage === 'closed_won' ? (
            <div className='space-y-4 rounded-lg border p-4'>
              <div className='space-y-1'>
                <div className='font-medium'>Purchase Order Attachment</div>
                <div className='text-muted-foreground text-sm'>
                  Upload PDF, image, or Excel files for the received PO.
                </div>
              </div>
              <div className='grid gap-3 md:grid-cols-2'>
                <div className='space-y-2'>
                  <Label htmlFor='po-file'>PO file</Label>
                  <Input
                    id='po-file'
                    type='file'
                    accept='.pdf,.png,.jpg,.jpeg,.webp,.xls,.xlsx'
                    onChange={(event) => setPoFile(event.target.files?.[0] ?? null)}
                  />
                </div>
                <div className='space-y-2'>
                  <Label htmlFor='po-file-description'>Description</Label>
                  <Input
                    id='po-file-description'
                    value={poFileDescription}
                    onChange={(event) => setPoFileDescription(event.target.value)}
                    placeholder='Optional note for this file'
                  />
                </div>
              </div>
              <Button
                type='button'
                variant='outline'
                onClick={() => uploadMutation.mutate()}
                isLoading={uploadMutation.isPending}
                disabled={!poFile}
              >
                <Icons.upload className='mr-2 h-4 w-4' />
                Upload PO
              </Button>
              {!attachmentItems.length ? (
                <div className='text-muted-foreground rounded-lg border border-dashed p-4 text-sm'>
                  No PO attachments uploaded yet.
                </div>
              ) : (
                <div className='space-y-2'>
                  {attachmentItems.map((attachment) => (
                    <div
                      key={attachment.id}
                      className='flex flex-col gap-2 rounded-lg border p-3 md:flex-row md:items-center md:justify-between'
                    >
                      <div className='space-y-1'>
                        <div className='font-medium'>{attachment.originalFileName}</div>
                        <div className='text-muted-foreground text-xs'>
                          {attachment.fileType ?? 'Unknown type'}
                          {attachment.fileSize
                            ? ` • ${formatNumber(attachment.fileSize)} bytes`
                            : ''}
                        </div>
                      </div>
                      <div className='flex gap-2'>
                        <Button asChild variant='outline' size='sm'>
                          <Link
                            href={`/api/crm/opportunities/${opportunityId}/po-attachments/${attachment.id}`}
                          >
                            View
                          </Link>
                        </Button>
                        <Button asChild variant='outline' size='sm'>
                          <Link
                            href={`/api/crm/opportunities/${opportunityId}/po-attachments/${attachment.id}?download=1`}
                          >
                            Download
                          </Link>
                        </Button>
                      </div>
                    </div>
                  ))}
                </div>
              )}
            </div>
          ) : null}
        </CardContent>
      </Card>

      <Dialog open={wonOpen} onOpenChange={setWonOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Mark Won</DialogTitle>
            <DialogDescription>
              PO received is the official trigger for closed won.
            </DialogDescription>
          </DialogHeader>
          <div className='grid gap-4 py-2'>
            <div className='space-y-2'>
              <Label htmlFor='po-number'>PO Number</Label>
              <Input
                id='po-number'
                value={poNumber}
                onChange={(e) => setPoNumber(e.target.value)}
              />
            </div>
            <div className='space-y-2'>
              <Label htmlFor='po-date'>PO Date</Label>
              <CrmDateInput value={poDate} onChange={setPoDate} className='w-full' />
            </div>
            <div className='grid gap-4 md:grid-cols-2'>
              <div className='space-y-2'>
                <Label htmlFor='po-amount'>PO Amount</Label>
                <CrmCurrencyInput
                  value={poAmount}
                  onChange={setPoAmount}
                  currencyLabel={poCurrency}
                />
              </div>
              <div className='space-y-2'>
                <Label>PO Currency</Label>
                <Select value={poCurrency} onValueChange={setPoCurrency}>
                  <SelectTrigger>
                    <SelectValue placeholder='Select currency' />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value='THB'>THB</SelectItem>
                    <SelectItem value='USD'>USD</SelectItem>
                    <SelectItem value='EUR'>EUR</SelectItem>
                  </SelectContent>
                </Select>
              </div>
            </div>
            <div className='space-y-2'>
              <Label htmlFor='won-remark'>Remark</Label>
              <CrmTextarea
                id='won-remark'
                value={wonRemark}
                onChange={(e) => setWonRemark(e.target.value)}
                size='md'
              />
            </div>
          </div>
          <DialogFooter>
            <Button variant='outline' onClick={() => setWonOpen(false)}>
              Cancel
            </Button>
            <Button
              isLoading={wonMutation.isPending}
              onClick={() =>
                wonMutation.mutate({
                  id: opportunityId,
                  values: {
                    poNumber,
                    poDate,
                    poAmount: poAmount.trim() ? Number(poAmount) : null,
                    poCurrency,
                    remark: wonRemark
                  }
                })
              }
            >
              Confirm Won
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={lostOpen} onOpenChange={setLostOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Mark Lost</DialogTitle>
            <DialogDescription>
              Lost reason is required for every closed lost outcome.
            </DialogDescription>
          </DialogHeader>
          <div className='grid gap-4 py-2'>
            <div className='space-y-2'>
              <Label>Lost Reason</Label>
              <Select value={lostReason} onValueChange={setLostReason}>
                <SelectTrigger>
                  <SelectValue placeholder='Select lost reason' />
                </SelectTrigger>
                <SelectContent>
                  {referenceData.lostReasons.map((item) => (
                    <SelectItem key={item.id} value={item.id}>
                      {item.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className='space-y-2'>
              <Label htmlFor='lost-competitor'>Lost Competitor</Label>
              <Input
                id='lost-competitor'
                value={lostCompetitor}
                onChange={(e) => setLostCompetitor(e.target.value)}
              />
            </div>
            <div className='space-y-2'>
              <Label htmlFor='lost-remark'>Lost Remark</Label>
              <CrmTextarea
                id='lost-remark'
                value={lostRemark}
                onChange={(e) => setLostRemark(e.target.value)}
                size='md'
              />
            </div>
          </div>
          <DialogFooter>
            <Button variant='outline' onClick={() => setLostOpen(false)}>
              Cancel
            </Button>
            <Button
              variant='destructive'
              isLoading={lostMutation.isPending}
              onClick={() =>
                lostMutation.mutate({
                  id: opportunityId,
                  values: {
                    lostReason,
                    lostCompetitor,
                    lostRemark
                  }
                })
              }
            >
              Confirm Lost
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={reopenOpen} onOpenChange={setReopenOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Reopen Opportunity</DialogTitle>
            <DialogDescription>Only lost opportunities can be reopened.</DialogDescription>
          </DialogHeader>
          <div className='space-y-2 py-2'>
            <Label htmlFor='reopen-reason'>Reopen Reason</Label>
            <CrmTextarea
              id='reopen-reason'
              value={reopenReason}
              onChange={(e) => setReopenReason(e.target.value)}
              size='md'
            />
          </div>
          <DialogFooter>
            <Button variant='outline' onClick={() => setReopenOpen(false)}>
              Cancel
            </Button>
            <Button
              isLoading={reopenMutation.isPending}
              onClick={() => reopenMutation.mutate({ id: opportunityId, reason: reopenReason })}
            >
              Reopen
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
}
