import { zodResolver } from '@hookform/resolvers/zod'
import { type ColumnDef } from '@tanstack/react-table'
import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip } from 'recharts'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useForm } from 'react-hook-form'
import { z } from 'zod'

import { DataTable } from '@/components/data-table/data-table'
import { DataTableToolbar } from '@/components/data-table/data-table-toolbar'
import { DealStageBadge, dealStageLabels } from '@/components/crm/deal-stage-badge'
import { DealStatusBadge, dealStatusLabels } from '@/components/crm/deal-status-badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@/components/ui/sheet'
import { useToast } from '@/components/ui/use-toast'
import { useContactsQuery } from '@/features/contacts/hooks'
import { useCreateDealMutation, useDealsQuery, useUpdateDealMutation } from '@/features/deals/hooks'
import { formatCurrency, formatDate } from '@/lib/utils'
import type { Contact, Deal, DealStage, DealStatus } from '@/types/crm'

const dealStatusList: DealStatus[] = ['new', 'in_progress', 'won', 'lost']
const dealStageList: DealStage[] = ['qualification', 'proposal', 'negotiation', 'closed']

const dealCreateSchema = z.object({
  title: z.string().min(3, 'Минимум 3 символа'),
  contactId: z.string().min(1, 'Введите ID контакта'),
  amount: z.string().optional(),
  currency: z.string().min(3).max(3).optional(),
  ownerId: z.string().optional(),
})

type DealCreateFormValues = z.infer<typeof dealCreateSchema>

const dealUpdateSchema = z.object({
  status: z.enum(dealStatusList),
  stage: z.enum(dealStageList),
  amount: z.string().optional(),
  currency: z.string().min(3).max(3).optional(),
})

type DealUpdateFormValues = z.infer<typeof dealUpdateSchema>

const mapAmount = (value?: string | null) => {
  if (!value) return 0
  const number = Number(value)
  return Number.isFinite(number) ? number : 0
}

const DealsPage = () => {
  const [search, setSearch] = useState('')
  const [statusFilter, setStatusFilter] = useState<'all' | DealStatus>('all')
  const [stageFilter, setStageFilter] = useState<'all' | DealStage>('all')
  const [ownerFilter, setOwnerFilter] = useState('')
  const [minAmount, setMinAmount] = useState('')
  const [maxAmount, setMaxAmount] = useState('')
  const [createOpen, setCreateOpen] = useState(false)
  const [dealToEdit, setDealToEdit] = useState<Deal | null>(null)
  const { toast } = useToast()

  const filters = useMemo(() => {
    const ownerNumber = ownerFilter ? Number(ownerFilter) : undefined
    const min = minAmount ? Number(minAmount) : undefined
    const max = maxAmount ? Number(maxAmount) : undefined
    return {
      status: statusFilter === 'all' ? undefined : [statusFilter],
      stage: stageFilter === 'all' ? undefined : stageFilter,
      ownerId: Number.isFinite(ownerNumber) ? ownerNumber : undefined,
      minAmount: Number.isFinite(min) ? min : undefined,
      maxAmount: Number.isFinite(max) ? max : undefined,
    }
  }, [statusFilter, stageFilter, ownerFilter, minAmount, maxAmount])

  const { data: deals = [], isLoading } = useDealsQuery(filters)
  const { data: contacts = [], isLoading: contactsLoading } = useContactsQuery({ pageSize: 100 })
  const filteredDeals = useMemo(() => {
    const query = search.trim().toLowerCase()
    if (!query) return deals
    return deals.filter((deal) => deal.title.toLowerCase().includes(query))
  }, [deals, search])

  const createDeal = useCreateDealMutation()
  const updateDeal = useUpdateDealMutation()

  const ownerOptions = useMemo(
    () =>
      Array.from(
        new Set(
          [
            ...deals.map((deal) => deal.owner_id),
            ...contacts.map((contact) => contact.owner_id).filter((id): id is number => typeof id === 'number'),
          ],
        ),
      )
        .filter((id) => id !== undefined && id !== null)
        .map((id) => ({ value: String(id), label: `Сотрудник #${id}` })),
    [contacts, deals],
  )

  const stats = useMemo(() => {
    const total = deals.length
    const pipeline = deals.reduce((acc, deal) => acc + mapAmount(deal.amount), 0)
    const won = deals.filter((deal) => deal.status === 'won')
    const wonAmount = won.reduce((acc, deal) => acc + mapAmount(deal.amount), 0)
    const conversion = total ? Math.round((won.length / total) * 100) : 0
    return { total, pipeline, wonAmount, conversion }
  }, [deals])

  const stageChartData = useMemo(
    () =>
      dealStageList.map((stage) => {
        const stageDeals = deals.filter((deal) => deal.stage === stage)
        return {
          stage: dealStageLabels[stage],
          count: stageDeals.length,
          value: stageDeals.reduce((acc, deal) => acc + mapAmount(deal.amount), 0),
        }
      }),
    [deals],
  )

  const handleEditDeal = useCallback((deal: Deal) => setDealToEdit(deal), [])

  const columns = useMemo<ColumnDef<Deal>[]>(
    () => [
      {
        accessorKey: 'title',
        header: 'Сделка',
        cell: ({ row }) => (
          <div>
            <p className="font-medium">{row.original.title}</p>
            <p className="text-xs text-muted-foreground">Контакт #{row.original.contact_id}</p>
          </div>
        ),
      },
      {
        accessorKey: 'amount',
        header: 'Сумма',
        cell: ({ row }) => (
          <div>
            <p className="font-medium">{formatCurrency(row.original.amount, row.original.currency ?? 'USD')}</p>
            <p className="text-xs text-muted-foreground">{row.original.currency ?? '—'}</p>
          </div>
        ),
      },
      {
        accessorKey: 'status',
        header: 'Статус',
        cell: ({ row }) => <DealStatusBadge status={row.original.status} />,
      },
      {
        accessorKey: 'stage',
        header: 'Этап',
        cell: ({ row }) => <DealStageBadge stage={row.original.stage} />,
      },
      {
        accessorKey: 'owner_id',
        header: 'Владелец',
        cell: ({ row }) => <span className="text-sm text-muted-foreground">Сотрудник #{row.original.owner_id}</span>,
      },
      {
        accessorKey: 'updated_at',
        header: 'Обновлена',
        cell: ({ row }) => <span className="text-sm text-muted-foreground">{formatDate(row.original.updated_at)}</span>,
      },
      {
        id: 'actions',
        header: '',
        cell: ({ row }) => (
          <Button variant="ghost" size="sm" onClick={() => handleEditDeal(row.original)}>
            Обновить
          </Button>
        ),
      },
    ],
    [handleEditDeal],
  )

  return (
    <div className="space-y-6">
      <header>
        <h1 className="text-2xl font-semibold text-foreground">Сделки</h1>
        <p className="text-sm text-muted-foreground">Следите за воронкой продаж и обновляйте статусы в один клик.</p>
      </header>

      <section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
        <StatCard title="Всего сделок" value={stats.total} description="Количество в текущем списке" />
        <StatCard title="Потенциал" value={formatCurrency(stats.pipeline)} description="Суммарный pipeline" />
        <StatCard title="Выиграно" value={formatCurrency(stats.wonAmount)} description="Сумма выигранных сделок" />
        <StatCard title="Конверсия" value={`${stats.conversion}%`} description="Выиграно от всех" />
      </section>

      <Card>
        <CardHeader>
          <CardTitle>Воронка по этапам</CardTitle>
          <CardDescription>Количество и сумма сделок на каждом этапе.</CardDescription>
        </CardHeader>
        <CardContent className="h-[280px]">
          <ResponsiveContainer width="100%" height="100%">
            <BarChart data={stageChartData}>
              <CartesianGrid strokeDasharray="3 3" opacity={0.3} />
              <XAxis dataKey="stage" tick={{ fill: 'currentColor', fontSize: 12 }} />
              <YAxis tick={{ fill: 'currentColor', fontSize: 12 }} />
              <Tooltip content={<StageTooltip />} cursor={{ fill: 'transparent' }} />
              <Bar dataKey="count" name="Сделки" fill="hsl(var(--primary))" radius={[8, 8, 0, 0]} />
            </BarChart>
          </ResponsiveContainer>
        </CardContent>
      </Card>

      <DataTable
        columns={columns}
        data={filteredDeals}
        isLoading={isLoading}
        renderToolbar={
          <DataTableToolbar
            searchPlaceholder="Поиск по названию"
            searchValue={search}
            onSearchChange={setSearch}
            actions={
              <Button className="gap-2" onClick={() => setCreateOpen(true)}>
                + Новая сделка
              </Button>
            }
          >
            <Select value={statusFilter} onValueChange={(value) => setStatusFilter(value as typeof statusFilter)}>
              <SelectTrigger className="w-[180px] bg-background">
                <SelectValue placeholder="Статус" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">Все статусы</SelectItem>
                {dealStatusList.map((status) => (
                  <SelectItem key={status} value={status}>
                    {dealStatusLabels[status]}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <Select value={stageFilter} onValueChange={(value) => setStageFilter(value as typeof stageFilter)}>
              <SelectTrigger className="w-[200px] bg-background">
                <SelectValue placeholder="Этап" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">Все этапы</SelectItem>
                {dealStageList.map((stage) => (
                  <SelectItem key={stage} value={stage}>
                    {dealStageLabels[stage]}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <Input
              type="number"
              placeholder="ID владельца"
              value={ownerFilter}
              onChange={(event) => setOwnerFilter(event.target.value)}
              className="w-[140px]"
            />
            <div className="flex items-center gap-2">
              <Input
                type="number"
                placeholder="Мин сумма"
                value={minAmount}
                onChange={(event) => setMinAmount(event.target.value)}
                className="w-[130px]"
              />
              <Input
                type="number"
                placeholder="Макс сумма"
                value={maxAmount}
                onChange={(event) => setMaxAmount(event.target.value)}
                className="w-[130px]"
              />
            </div>
          </DataTableToolbar>
        }
      />

      <DealCreateDrawer
        open={createOpen}
        onOpenChange={setCreateOpen}
        isSubmitting={createDeal.isPending}
        contacts={contacts}
        contactsLoading={contactsLoading}
        ownerOptions={ownerOptions}
        onSubmit={async (values) => {
          const payload = {
            title: values.title,
            contact_id: Number(values.contactId),
            amount: values.amount ? Number(values.amount) : undefined,
            currency: values.currency ? values.currency.toUpperCase() : undefined,
            owner_id: values.ownerId && values.ownerId !== 'auto' ? Number(values.ownerId) : undefined,
          }
          try {
            await createDeal.mutateAsync(payload)
            toast({ title: 'Сделка создана', description: 'Запись появилась в воронке.' })
            setCreateOpen(false)
          } catch (error) {
            toast({ title: 'Не удалось создать сделку', description: error instanceof Error ? error.message : 'Попробуйте снова', variant: 'destructive' })
          }
        }}
      />

      <DealUpdateDrawer
        deal={dealToEdit}
        open={Boolean(dealToEdit)}
        onOpenChange={(open) => {
          if (!open) setDealToEdit(null)
        }}
        isSubmitting={updateDeal.isPending}
        onSubmit={async (values) => {
          if (!dealToEdit) return
          const payload = {
            status: values.status,
            stage: values.stage,
            amount: values.amount ? Number(values.amount) : undefined,
            currency: values.currency ? values.currency.toUpperCase() : undefined,
          }
          try {
            await updateDeal.mutateAsync({ dealId: dealToEdit.id, payload })
            toast({ title: 'Сделка обновлена', description: 'Статус и этап сохранены.' })
            setDealToEdit(null)
          } catch (error) {
            toast({ title: 'Ошибка обновления', description: error instanceof Error ? error.message : 'Попробуйте позже', variant: 'destructive' })
          }
        }}
      />
    </div>
  )
}

interface StatCardProps {
  title: string
  value: string | number
  description: string
}

const StatCard = ({ title, value, description }: StatCardProps) => (
  <Card>
    <CardHeader>
      <CardTitle className="text-base">{title}</CardTitle>
      <CardDescription>{description}</CardDescription>
    </CardHeader>
    <CardContent>
      <p className="text-3xl font-semibold">{value}</p>
    </CardContent>
  </Card>
)

const StageTooltip = ({ active, payload }: { active?: boolean; payload?: Array<{ payload: { stage: string; count: number; value: number } }> }) => {
  if (!active || !payload?.length) return null
  const [{ payload: data }] = payload
  return (
    <div className="rounded-md border bg-background/90 px-4 py-2 text-sm shadow">
      <p className="font-semibold">{data.stage}</p>
      <p>Сделок: {data.count}</p>
      <p>Сумма: {formatCurrency(data.value)}</p>
    </div>
  )
}

interface DealCreateDrawerProps {
  open: boolean
  onOpenChange: (open: boolean) => void
  onSubmit: (values: DealCreateFormValues) => Promise<void>
  isSubmitting: boolean
  contacts: Contact[]
  contactsLoading: boolean
  ownerOptions: Array<{ value: string; label: string }>
}

const DealCreateDrawer = ({ open, onOpenChange, onSubmit, isSubmitting, contacts, contactsLoading, ownerOptions }: DealCreateDrawerProps) => {
  const form = useForm<DealCreateFormValues>({
    resolver: zodResolver(dealCreateSchema),
    defaultValues: { title: '', contactId: '', amount: '', currency: 'USD', ownerId: 'auto' },
  })

  const handleSubmit = async (values: DealCreateFormValues) => {
    await onSubmit(values)
    form.reset({ title: '', contactId: '', amount: '', currency: 'USD', ownerId: 'auto' })
  }

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="w-full max-w-lg">
        <SheetHeader>
          <SheetTitle>Новая сделка</SheetTitle>
          <SheetDescription>Заполните данные для создания сделки.</SheetDescription>
        </SheetHeader>
        <Form {...form}>
          <form onSubmit={form.handleSubmit(handleSubmit)} className="mt-6 space-y-4">
            <FormField
              control={form.control}
              name="title"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Название</FormLabel>
                  <FormControl>
                    <Input placeholder="Реставрация сайта" {...field} />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="contactId"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Контакт</FormLabel>
                  <Select value={field.value} onValueChange={field.onChange} disabled={contactsLoading || !contacts.length}>
                    <FormControl>
                      <SelectTrigger>
                        <SelectValue placeholder={contactsLoading ? 'Загружаем контакты…' : 'Выберите контакт'} />
                      </SelectTrigger>
                    </FormControl>
                    <SelectContent>
                      {contacts.map((contact) => (
                        <SelectItem key={contact.id} value={String(contact.id)}>
                          {contact.name} · #{contact.id}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <FormDescription>
                    {contacts.length ? 'Контакт будет связан со сделкой.' : 'Сначала создайте контакт в разделе «Контакты».'}
                  </FormDescription>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="amount"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Сумма</FormLabel>
                  <FormControl>
                    <Input type="number" placeholder="10000" {...field} />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="currency"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Валюта</FormLabel>
                  <FormControl>
                    <Input placeholder="USD" {...field} />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="ownerId"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Владелец (необязательно)</FormLabel>
                  <Select value={field.value} onValueChange={field.onChange}>
                    <FormControl>
                      <SelectTrigger>
                        <SelectValue placeholder={ownerOptions.length ? 'Выберите владельца' : 'Только автоназначение'} />
                      </SelectTrigger>
                    </FormControl>
                    <SelectContent>
                      <SelectItem value="auto">Назначить автоматически</SelectItem>
                      {ownerOptions.map((option) => (
                        <SelectItem key={option.value} value={option.value}>
                          {option.label}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <FormDescription>При отсутствии выбора сделка будет закреплена за вами.</FormDescription>
                  <FormMessage />
                </FormItem>
              )}
            />
            <div className="flex justify-end gap-2 pt-4">
              <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
                Отмена
              </Button>
              <Button type="submit" disabled={isSubmitting}>
                {isSubmitting ? 'Создаём…' : 'Создать'}
              </Button>
            </div>
          </form>
        </Form>
      </SheetContent>
    </Sheet>
  )
}

interface DealUpdateDrawerProps {
  deal: Deal | null
  open: boolean
  onOpenChange: (open: boolean) => void
  onSubmit: (values: DealUpdateFormValues) => Promise<void>
  isSubmitting: boolean
}

const DealUpdateDrawer = ({ deal, open, onOpenChange, onSubmit, isSubmitting }: DealUpdateDrawerProps) => {
  const form = useForm<DealUpdateFormValues>({
    resolver: zodResolver(dealUpdateSchema),
    defaultValues: { status: 'new', stage: 'qualification', amount: '', currency: 'USD' },
  })

  useEffect(() => {
    if (deal) {
      form.reset({
        status: deal.status,
        stage: deal.stage,
        amount: deal.amount ?? '',
        currency: deal.currency ?? 'USD',
      })
    }
  }, [deal, form])

  if (!deal) return null

  const handleSubmit = async (values: DealUpdateFormValues) => {
    await onSubmit(values)
  }

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent className="w-full max-w-lg">
        <SheetHeader>
          <SheetTitle>Обновление сделки</SheetTitle>
          <SheetDescription>Измените статус, этап или сумму.</SheetDescription>
        </SheetHeader>
        <Form {...form}>
          <form onSubmit={form.handleSubmit(handleSubmit)} className="mt-6 space-y-4">
            <FormField
              control={form.control}
              name="status"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Статус</FormLabel>
                  <Select value={field.value} onValueChange={field.onChange}>
                    <FormControl>
                      <SelectTrigger>
                        <SelectValue placeholder="Выберите статус" />
                      </SelectTrigger>
                    </FormControl>
                    <SelectContent>
                      {dealStatusList.map((status) => (
                        <SelectItem key={status} value={status}>
                          {dealStatusLabels[status]}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="stage"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Этап</FormLabel>
                  <Select value={field.value} onValueChange={field.onChange}>
                    <FormControl>
                      <SelectTrigger>
                        <SelectValue placeholder="Выберите этап" />
                      </SelectTrigger>
                    </FormControl>
                    <SelectContent>
                      {dealStageList.map((stage) => (
                        <SelectItem key={stage} value={stage}>
                          {dealStageLabels[stage]}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="amount"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Сумма</FormLabel>
                  <FormControl>
                    <Input type="number" placeholder="0" {...field} />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <FormField
              control={form.control}
              name="currency"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Валюта</FormLabel>
                  <FormControl>
                    <Input placeholder="USD" {...field} />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            <div className="flex justify-end gap-2 pt-4">
              <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
                Отмена
              </Button>
              <Button type="submit" disabled={isSubmitting}>
                {isSubmitting ? 'Сохраняем…' : 'Сохранить'}
              </Button>
            </div>
          </form>
        </Form>
      </SheetContent>
    </Sheet>
  )
}

export default DealsPage
