import { useMemo, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import dayjs from 'dayjs'
import { Button, Card, Typography, message } from 'antd'
import CareTable from '../../components/CareTable'
import {
  CalculatorOutlined,
  DownloadOutlined,
  LeftOutlined,
  RightOutlined } from '@ant-design/icons'
import client, { apiPrefix, unwrap, type ApiResponse } from '../../api/client'
import { money } from './homesShared'

type PublishRow = {
  id?: number | null
  employee: string
  yearMonth: string
  internetCount?: number
  internetAmount?: number
  homeCount?: number
  homeAmount?: number
  balanceCount?: number
  balanceAmount?: number
  settleAmount?: number
  issued?: boolean
  status?: string
  consent?: string
  taxInvoice?: string
  withdrawStatus?: string
  mismatched?: boolean
}

type PublishResult = {
  yearMonth: string
  total: number
  list: PublishRow[]
}

const num = (v: unknown) => {
  const n = Number(v ?? 0)
  return Number.isFinite(n) ? n : 0
}
const cell = (v: unknown) => (num(v) === 0 ? '' : num(v).toLocaleString())
const moneyCell = (v: unknown, mismatched?: boolean) => {
  if (num(v) === 0) return ''
  return <span className={mismatched ? 'invoice-mismatch' : undefined}>{money(v)}</span>
}

export default function InvoicePublishPage() {
  const qc = useQueryClient()
  const [cursor, setCursor] = useState(() => dayjs().startOf('month'))
  const yearMonth = cursor.format('YYYY-MM')

  const query = useQuery({
    queryKey: ['homes-invoice-publish', yearMonth],
    queryFn: async () => {
      const { data } = await client.get<ApiResponse<PublishResult>>(`${apiPrefix()}/homes/invoices/publish`, {
        params: { yearMonth } })
      return unwrap(data)
    } })

  const issue = useMutation({
    mutationFn: async (row: PublishRow) => {
      const { data } = await client.post(`${apiPrefix()}/homes/invoices/publish/issue`, {
        yearMonth: row.yearMonth || yearMonth,
        employee: row.employee })
      return unwrap(data as ApiResponse)
    },
    onSuccess: () => {
      message.success('정산서를 발행했습니다.')
      qc.invalidateQueries({ queryKey: ['homes-invoice-publish'] })
    },
    onError: (e: Error) => message.error(e.message || '발행에 실패했습니다.') })

  const download = async () => {
    try {
      const { data } = await client.get(`${apiPrefix()}/homes/invoices/publish/export`, {
        params: { yearMonth },
        responseType: 'blob' })
      const url = URL.createObjectURL(data)
      const a = document.createElement('a')
      a.href = url
      a.download = `정산서발행_${yearMonth}.csv`
      a.click()
      URL.revokeObjectURL(url)
    } catch {
      message.error('엑셀 다운로드에 실패했습니다.')
    }
  }

  const columns = useMemo(() => [
    {
      title: '직원',
      dataIndex: 'employee',
      width: 100,
      align: 'center' as const,
      render: (v: string, row: PublishRow) => (
        <span className={row.mismatched ? 'invoice-mismatch' : undefined}>{v}</span>
      ) },
    {
      title: '인터넷',
      dataIndex: 'internetCount',
      width: 80,
      align: 'center' as const,
      render: (v: unknown, row: PublishRow) => (
        <span className={row.mismatched ? 'invoice-mismatch' : undefined}>{cell(v)}</span>
      ) },
    {
      title: '인터넷금액',
      dataIndex: 'internetAmount',
      width: 110,
      align: 'center' as const,
      render: (v: unknown, row: PublishRow) => moneyCell(v, row.mismatched) },
    {
      title: '홈렌탈',
      dataIndex: 'homeCount',
      width: 80,
      align: 'center' as const,
      render: (v: unknown, row: PublishRow) => (
        <span className={row.mismatched ? 'invoice-mismatch' : undefined}>{cell(v)}</span>
      ) },
    {
      title: '홈렌탈금액',
      dataIndex: 'homeAmount',
      width: 110,
      align: 'center' as const,
      render: (v: unknown, row: PublishRow) => moneyCell(v, row.mismatched) },
    {
      title: '후정산',
      dataIndex: 'balanceCount',
      width: 80,
      align: 'center' as const,
      render: (v: unknown, row: PublishRow) => (
        <span className={row.mismatched ? 'invoice-mismatch' : undefined}>{cell(v)}</span>
      ) },
    {
      title: '후정산금액',
      dataIndex: 'balanceAmount',
      width: 110,
      align: 'center' as const,
      render: (v: unknown, row: PublishRow) => moneyCell(v, row.mismatched) },
    {
      title: '정산금액',
      dataIndex: 'settleAmount',
      width: 110,
      align: 'center' as const,
      render: (v: unknown, row: PublishRow) => moneyCell(v, row.mismatched) },
    {
      title: '정산서발행',
      width: 100,
      align: 'center' as const,
      render: (_: unknown, row: PublishRow) => (
        row.issued ? (
          <Button type="link" size="small" className="invoice-issued-link" onClick={() => issue.mutate(row)}>
            재발행
          </Button>
        ) : (
          <Button
            type="link"
            size="small"
            className="invoice-issue-link"
            loading={issue.isPending}
            onClick={() => issue.mutate(row)}
          >
            발행
          </Button>
        )
      ) },
    {
      title: '동의',
      dataIndex: 'consent',
      width: 80,
      align: 'center' as const,
      render: (v: string) => v || '-' },
    {
      title: '계산서',
      dataIndex: 'taxInvoice',
      width: 80,
      align: 'center' as const,
      render: (v: string) => v || '-' },
    {
      title: '출금상태',
      dataIndex: 'withdrawStatus',
      width: 90,
      align: 'center' as const,
      render: (v: string) => v || '-' },
  ], [issue])

  return (
    <div className="stock-page invoice-publish-page">
      <div className="stock-title">
        <div>
          <h2>
            <CalculatorOutlined className="product-title-icon" />
            정산서발행
          </h2>
          <p>
            직원 및 하부점에 정산서를 발행 및 관리하실 수 있습니다. (계약 진행상태가 완료인 자료만 정산서를 발행하실 수 있습니다.)
          </p>
        </div>
      </div>

      <Card className="stock-filter-card invoice-month-card" size="small">
        <div className="invoice-month-bar">
          <div className="invoice-month-nav">
            <button type="button" aria-label="이전 달" onClick={() => setCursor((c) => c.subtract(1, 'month'))}>
              <LeftOutlined />
            </button>
            <span>{cursor.format('YYYY년 M월')}</span>
            <button type="button" aria-label="다음 달" onClick={() => setCursor((c) => c.add(1, 'month'))}>
              <RightOutlined />
            </button>
          </div>
          <Button type="link" icon={<DownloadOutlined />} onClick={download}>엑셀다운로드</Button>
        </div>
      </Card>

      <Card className="stock-table-card" size="small">
        <CareTable
          rowKey={(row) => `${row.employee}-${row.yearMonth}`}
          size="small"
          loading={query.isLoading}
          dataSource={query.data?.list}
          columns={columns}
          pagination={false}
          scroll={{ x: 1200 }}
          locale={{ emptyText: '등록된 자료가 없습니다.' }}
          rowClassName={(row) => (row.mismatched ? 'invoice-row-mismatch' : '')}
        />
        <div className="invoice-notes">
          <Typography.Text type="secondary">
            * 정산서발행 시 자료의 양에 따라 처리시간이 오래 걸릴 수 있습니다.
          </Typography.Text>
          <Typography.Text type="secondary">
            * 붉은색 표기는 추가/수정으로 인해 발행정산서와 일치하지 않는 내용입니다. (필요한 경우 재발행하시면 해결됩니다.)
          </Typography.Text>
        </div>
      </Card>
    </div>
  )
}
