import { useState } from 'react'
import Alert from '@mui/material/Alert'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Chip from '@mui/material/Chip'
import Dialog from '@mui/material/Dialog'
import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent'
import DialogTitle from '@mui/material/DialogTitle'
import FormControlLabel from '@mui/material/FormControlLabel'
import Stack from '@mui/material/Stack'
import Switch from '@mui/material/Switch'
import TextField from '@mui/material/TextField'
import Typography from '@mui/material/Typography'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { Controller, useForm } from 'react-hook-form'
import {
  createMyAddress,
  deleteMyAddress,
  fetchMyAddresses,
  setMyAddressDefault,
  updateMyAddress,
} from '@/entities/user/api/address-api'
import type { ShippingAddress } from '@/entities/user/model/types'
import { AddressMapPicker } from '@/features/address-map-picker'

export function AddressesPage() {
  const queryClient = useQueryClient()
  const [open, setOpen] = useState(false)
  const [editing, setEditing] = useState<ShippingAddress | null>(null)

  const addressesQuery = useQuery({
    queryKey: ['me', 'addresses'],
    queryFn: fetchMyAddresses,
  })

  const form = useForm<{
    label: string
    recipientName: string
    recipientPhone: string
    addressLine: string
    comment: string
    lat: number | null
    lng: number | null
    isDefault: boolean
  }>({
    defaultValues: {
      label: '',
      recipientName: '',
      recipientPhone: '',
      addressLine: '',
      comment: '',
      lat: null,
      lng: null,
      isDefault: false,
    },
    mode: 'onChange',
  })

  const createMut = useMutation({
    mutationFn: async () => {
      const v = form.getValues()
      if (v.lat === null || v.lng === null) throw new Error('Выберите точку на карте')
      await createMyAddress({
        label: v.label.trim() || null,
        recipientName: v.recipientName.trim(),
        recipientPhone: v.recipientPhone.trim(),
        addressLine: v.addressLine.trim(),
        comment: v.comment.trim() || null,
        lat: v.lat,
        lng: v.lng,
        isDefault: v.isDefault,
      })
    },
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ['me', 'addresses'] })
      setOpen(false)
    },
  })

  const updateMut = useMutation({
    mutationFn: async () => {
      const v = form.getValues()
      if (v.lat === null || v.lng === null) throw new Error('Выберите точку на карте')
      await updateMyAddress(editing!.id, {
        label: v.label.trim() || null,
        recipientName: v.recipientName.trim(),
        recipientPhone: v.recipientPhone.trim(),
        addressLine: v.addressLine.trim(),
        comment: v.comment.trim() || null,
        lat: v.lat,
        lng: v.lng,
        isDefault: v.isDefault,
      })
    },
    onSuccess: () => {
      void queryClient.invalidateQueries({ queryKey: ['me', 'addresses'] })
      setOpen(false)
    },
  })

  const deleteMut = useMutation({
    mutationFn: (id: string) => deleteMyAddress(id),
    onSuccess: () => void queryClient.invalidateQueries({ queryKey: ['me', 'addresses'] }),
  })

  const defaultMut = useMutation({
    mutationFn: (id: string) => setMyAddressDefault(id),
    onSuccess: () => void queryClient.invalidateQueries({ queryKey: ['me', 'addresses'] }),
  })

  const error = createMut.error ?? updateMut.error ?? deleteMut.error ?? defaultMut.error

  const items = addressesQuery.data?.items ?? []

  const openCreate = () => {
    setEditing(null)
    form.reset({
      label: '',
      recipientName: '',
      recipientPhone: '',
      addressLine: '',
      comment: '',
      lat: null,
      lng: null,
      isDefault: items.length === 0,
    })
    setOpen(true)
  }

  const openEdit = (a: ShippingAddress) => {
    setEditing(a)
    form.reset({
      label: a.label ?? '',
      recipientName: a.recipientName,
      recipientPhone: a.recipientPhone,
      addressLine: a.addressLine,
      comment: a.comment ?? '',
      lat: a.lat,
      lng: a.lng,
      isDefault: a.isDefault,
    })
    setOpen(true)
  }

  return (
    <Box>
      <Typography variant="h4" gutterBottom>
        Адреса доставки
      </Typography>

      <Typography color="text.secondary" sx={{ mb: 2 }}>
        Можно добавить несколько адресов. Для каждого адреса задаются ФИО и телефон получателя отдельно.
      </Typography>

      <Stack direction="row" spacing={2} sx={{ mb: 2 }}>
        <Button variant="contained" onClick={openCreate}>
          Добавить адрес
        </Button>
      </Stack>

      {addressesQuery.isError && (
        <Alert severity="error" sx={{ mb: 2 }}>
          Не удалось загрузить адреса. Проверьте, что вы вошли в аккаунт и сервер запущен.
        </Alert>
      )}
      {error && (
        <Alert severity="error" sx={{ mb: 2 }}>
          {(error as Error).message}
        </Alert>
      )}

      <Stack spacing={2}>
        {items.map((a) => (
          <Box
            key={a.id}
            sx={{
              border: 1,
              borderColor: 'divider',
              borderRadius: 2,
              p: 2,
              bgcolor: 'background.paper',
            }}
          >
            <Stack direction={{ xs: 'column', sm: 'row' }} spacing={1} sx={{ alignItems: { sm: 'center' } }}>
              <Typography sx={{ fontWeight: 700, flexGrow: 1 }}>{a.label?.trim() ? a.label : 'Адрес'}</Typography>
              {a.isDefault && <Chip label="По умолчанию" color="primary" size="small" />}
            </Stack>

            <Typography sx={{ mt: 1 }}>{a.addressLine}</Typography>
            <Typography color="text.secondary" variant="body2" sx={{ mt: 0.5 }}>
              Получатель: {a.recipientName} · {a.recipientPhone}
            </Typography>
            {a.comment && (
              <Typography color="text.secondary" variant="body2" sx={{ mt: 0.5 }}>
                Комментарий: {a.comment}
              </Typography>
            )}

            <Stack direction="row" spacing={1} sx={{ mt: 1.5, flexWrap: 'wrap' }}>
              {!a.isDefault && (
                <Button size="small" onClick={() => defaultMut.mutate(a.id)} disabled={defaultMut.isPending}>
                  Сделать основным
                </Button>
              )}
              <Button size="small" onClick={() => openEdit(a)}>
                Изменить
              </Button>
              <Button
                size="small"
                color="error"
                disabled={deleteMut.isPending}
                onClick={() => {
                  if (!confirm('Удалить адрес?')) return
                  deleteMut.mutate(a.id)
                }}
              >
                Удалить
              </Button>
            </Stack>
          </Box>
        ))}

        {addressesQuery.isSuccess && items.length === 0 && (
          <Alert severity="info">Адресов пока нет — добавьте первый адрес доставки.</Alert>
        )}
      </Stack>

      <Dialog open={open} onClose={() => setOpen(false)} fullWidth maxWidth="md">
        <DialogTitle>{editing ? 'Редактировать адрес' : 'Новый адрес'}</DialogTitle>
        <DialogContent>
          <Stack spacing={2} sx={{ mt: 1 }}>
            <Controller
              control={form.control}
              name="label"
              render={({ field }) => <TextField label="Метка (например: Дом/Работа)" fullWidth {...field} />}
            />
            <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>
              <Controller
                control={form.control}
                name="recipientName"
                render={({ field }) => <TextField label="ФИО получателя" fullWidth required {...field} />}
              />
              <Controller
                control={form.control}
                name="recipientPhone"
                render={({ field }) => <TextField label="Телефон получателя" fullWidth required {...field} />}
              />
            </Stack>

            <Controller
              control={form.control}
              name="addressLine"
              render={({ field }) => <TextField label="Адрес" fullWidth required {...field} />}
            />
            <Controller
              control={form.control}
              name="comment"
              render={({ field }) => <TextField label="Комментарий (необязательно)" fullWidth {...field} />}
            />

            <Controller
              control={form.control}
              name="lat"
              render={({ field: latField }) => (
                <Controller
                  control={form.control}
                  name="lng"
                  render={({ field: lngField }) => (
                    <AddressMapPicker
                      value={
                        latField.value !== null && lngField.value !== null
                          ? { lat: latField.value, lng: lngField.value }
                          : null
                      }
                      onChange={(v) => {
                        latField.onChange(v.lat)
                        lngField.onChange(v.lng)
                        if (v.addressLine) form.setValue('addressLine', v.addressLine, { shouldDirty: true })
                      }}
                    />
                  )}
                />
              )}
            />

            <Controller
              control={form.control}
              name="isDefault"
              render={({ field }) => (
                <FormControlLabel
                  control={<Switch checked={Boolean(field.value)} onChange={(_, v) => field.onChange(v)} />}
                  label="Адрес по умолчанию"
                />
              )}
            />
          </Stack>
        </DialogContent>
        <DialogActions>
          <Button onClick={() => setOpen(false)}>Отмена</Button>
          <Button
            variant="contained"
            onClick={() => (editing ? updateMut.mutate() : createMut.mutate())}
            disabled={
              createMut.isPending ||
              updateMut.isPending ||
              !form.watch('recipientName').trim() ||
              !form.watch('recipientPhone').trim() ||
              !form.watch('addressLine').trim()
            }
          >
            Сохранить
          </Button>
        </DialogActions>
      </Dialog>
    </Box>
  )
}
