import {
  Button,
  Checkbox,
  Input,
  message,
  Modal,
  Popconfirm,
  Select,
  Space,
  Table,
  Tabs,
  Typography
} from 'antd'
import { ColumnsType } from 'antd/lib/table'
import { useEffect, useMemo, useState } from 'react'

import {
  getApiV1DevopsBillingProxyApiV1BillingUnitsExport,
  usePostApiV1DevopsBillingProxyApiV1BillingUnitsImport
} from 'apiClient/services/billing'

import {
  buildCsv,
  countCsvRows,
  createTemplateId,
  loadTemplates,
  parseCsv,
  SAMPLE_UNIT_CSV,
  saveTemplates,
  substitutePlaceholders,
  substituteRow,
  UnitRow,
  UnitTemplate
} from './unitTemplate'

const triggerDownload = (blob: Blob, filename: string) => {
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = filename
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
}

interface UnitTemplateModalProps {
  open: boolean
  onClose?: () => void
}

export const UnitTemplateModal = ({
  open,
  onClose: _onClose
}: UnitTemplateModalProps) => {
  const [templates, setTemplates] = useState<UnitTemplate[]>(() =>
    loadTemplates()
  )
  const [activeTab, setActiveTab] = useState('templates')
  const [preselectId, setPreselectId] = useState('')

  useEffect(() => {
    saveTemplates(templates)
  }, [templates])

  const handleUse = (id: string) => {
    setPreselectId(id)
    setActiveTab('apply')
  }

  return (
    <Modal
      title="Unit Templates"
      centered
      visible={open}
      onCancel={_onClose}
      width={1100}
      footer={null}
    >
      <Tabs activeKey={activeTab} onChange={setActiveTab}>
        <Tabs.TabPane tab="Templates" key="templates">
          <TemplatesTab
            templates={templates}
            onChange={setTemplates}
            onUse={handleUse}
          />
        </Tabs.TabPane>
        <Tabs.TabPane tab="Apply" key="apply">
          <ApplyTab templates={templates} preselectId={preselectId} />
        </Tabs.TabPane>
        <Tabs.TabPane tab="Export" key="export">
          <ExportTab />
        </Tabs.TabPane>
      </Tabs>
    </Modal>
  )
}

interface TemplatesTabProps {
  templates: UnitTemplate[]
  onChange: (next: UnitTemplate[]) => void
  onUse: (id: string) => void
}

const TemplatesTab = ({ templates, onChange, onUse }: TemplatesTabProps) => {
  const [mode, setMode] = useState<'list' | 'edit'>('list')
  const [editId, setEditId] = useState<string | null>(null)
  const [name, setName] = useState('')
  const [csv, setCsv] = useState('')

  const rowsCount = useMemo(() => countCsvRows(csv), [csv])

  const startNew = () => {
    setEditId(null)
    setName('')
    setCsv(SAMPLE_UNIT_CSV)
    setMode('edit')
  }

  const startEdit = (template: UnitTemplate) => {
    setEditId(template.id)
    setName(template.name)
    setCsv(template.csv)
    setMode('edit')
  }

  const cancelEdit = () => {
    setMode('list')
    setEditId(null)
    setName('')
    setCsv('')
  }

  const save = () => {
    const trimmedName = name.trim()
    if (!trimmedName) {
      message.error('Template name is required.')
      return
    }
    if (editId) {
      onChange(
        templates.map((t) =>
          t.id === editId ? { id: editId, name: trimmedName, csv } : t
        )
      )
    } else {
      onChange([
        ...templates,
        { id: createTemplateId(), name: trimmedName, csv }
      ])
    }
    cancelEdit()
  }

  const remove = (id: string) => {
    onChange(templates.filter((t) => t.id !== id))
  }

  const columns: ColumnsType<UnitTemplate> = [
    { title: 'Name', dataIndex: 'name' },
    {
      title: 'Units',
      width: 100,
      render: (_value, record) => countCsvRows(record.csv)
    },
    {
      title: 'Actions',
      width: 240,
      render: (_value, record) => (
        <Space>
          <Button type="link" onClick={() => onUse(record.id)}>
            Use
          </Button>
          <Button type="link" onClick={() => startEdit(record)}>
            Edit
          </Button>
          <Popconfirm
            title="Delete this template?"
            okText="Yes"
            cancelText="No"
            onConfirm={() => remove(record.id)}
          >
            <Button type="link">Delete</Button>
          </Popconfirm>
        </Space>
      )
    }
  ]

  if (mode === 'edit') {
    return (
      <Space direction="vertical" style={{ width: '100%' }} size="middle">
        <div>
          <Typography.Text strong>Name</Typography.Text>
          <Input
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="e.g. Standard SKU bundle"
          />
        </div>
        <div>
          <Typography.Text strong>Units CSV</Typography.Text>
          <Typography.Paragraph type="secondary" style={{ marginBottom: 4 }}>
            Paste the full exported units CSV (all columns preserved). Only
            unit_key needs placeholders: write {'{provider}'} and {'{region}'}{' '}
            for the provider/region segments. The provider/region columns are
            filled from Apply inputs.
          </Typography.Paragraph>
          <Input.TextArea
            value={csv}
            onChange={(e) => setCsv(e.target.value)}
            rows={10}
            style={{ fontFamily: 'monospace' }}
          />
        </div>
        <Typography.Text type="secondary">
          {rowsCount} unit row(s)
        </Typography.Text>
        <Space>
          <Button type="primary" onClick={save} disabled={!name.trim()}>
            Save
          </Button>
          <Button onClick={() => setCsv(SAMPLE_UNIT_CSV)}>Load sample</Button>
          <Button onClick={cancelEdit}>Cancel</Button>
        </Space>
      </Space>
    )
  }

  return (
    <Space direction="vertical" style={{ width: '100%' }} size="middle">
      <Button type="primary" onClick={startNew}>
        New template
      </Button>
      <Table<UnitTemplate>
        columns={columns}
        dataSource={templates}
        rowKey="id"
        size="small"
        pagination={false}
      />
    </Space>
  )
}

interface ApplyTabProps {
  templates: UnitTemplate[]
  preselectId: string
}

const ApplyTab = ({ templates, preselectId }: ApplyTabProps) => {
  const [templateId, setTemplateId] = useState(
    preselectId || templates[0]?.id || ''
  )
  const [providerKey, setProviderKey] = useState('')
  const [providerColumn, setProviderColumn] = useState('')
  const [providerLinked, setProviderLinked] = useState(true)
  const [regionKey, setRegionKey] = useState('')
  const [regionColumn, setRegionColumn] = useState('')
  const [regionLinked, setRegionLinked] = useState(true)
  const [prices, setPrices] = useState<Record<string, string>>({})
  const { mutateAsync: importUnits, isLoading: isImporting } =
    usePostApiV1DevopsBillingProxyApiV1BillingUnitsImport()

  const template = templates.find((t) => t.id === templateId)
  const parsed = useMemo(
    () => (template ? parseCsv(template.csv) : { headers: [], rows: [] }),
    [template]
  )
  const { headers, rows } = parsed

  const effectiveProviderColumn = providerLinked ? providerKey : providerColumn
  const effectiveRegionColumn = regionLinked ? regionKey : regionColumn

  const handleProviderLinkChange = (checked: boolean) => {
    if (!checked) setProviderColumn(providerKey)
    setProviderLinked(checked)
  }

  const handleRegionLinkChange = (checked: boolean) => {
    if (!checked) setRegionColumn(regionKey)
    setRegionLinked(checked)
  }

  useEffect(() => {
    if (preselectId) setTemplateId(preselectId)
  }, [preselectId])

  useEffect(() => {
    const current = templates.find((t) => t.id === templateId)
    const defaults: Record<string, string> = {}
    parseCsv(current?.csv || '').rows.forEach((row, index) => {
      defaults[String(index)] = (row.price || '').trim()
    })
    setPrices(defaults)
  }, [templateId, templates])

  const previewCsv = useMemo(() => {
    if (!rows.length) return ''
    const outputHeaders = headers.filter((header) => header !== 'group_id')
    return buildCsv(
      rows.map((row, index) => {
        const substituted = substituteRow(row, {
          provider: providerKey,
          region: regionKey
        })
        if ('provider' in substituted) {
          substituted.provider = effectiveProviderColumn
        }
        if ('region' in substituted) {
          substituted.region = effectiveRegionColumn
        }
        return {
          ...substituted,
          price:
            prices[String(index)] !== undefined
              ? prices[String(index)]
              : row.price || ''
        }
      }),
      outputHeaders
    )
  }, [
    rows,
    headers,
    prices,
    providerKey,
    regionKey,
    effectiveProviderColumn,
    effectiveRegionColumn
  ])

  const handleImport = async () => {
    if (!providerKey.trim()) {
      message.error('Provider key is required.')
      return
    }
    if (!providerLinked && !providerColumn.trim()) {
      message.error('Provider column is required (or link it to the key).')
      return
    }
    if (!regionKey.trim()) {
      message.error('Region key is required.')
      return
    }
    if (!regionLinked && !regionColumn.trim()) {
      message.error('Region column is required (or link it to the key).')
      return
    }
    const missing: string[] = []
    rows.forEach((_row, index) => {
      if (!(prices[String(index)] || '').trim()) {
        missing.push(String(index + 1))
      }
    })
    if (missing.length) {
      message.error(`Missing price on row(s): ${missing.join(', ')}`)
      return
    }
    try {
      const response = await importUnits({
        data: {
          file: new File([previewCsv], 'units-import.csv', {
            type: 'text/csv'
          })
        }
      })
      message.success(
        `Import successful! Imported ${
          response.data.imported_rows ?? 0
        } row(s).`
      )
    } catch (e: any) {
      message.error(e?.response?.data?.message || 'Import failed.')
    }
  }

  const columns: ColumnsType<UnitRow> = [
    {
      title: 'Unit Key',
      render: (_value, row) =>
        substitutePlaceholders(row.unit_key || '', {
          provider: providerKey,
          region: regionKey
        })
    },
    { title: 'Category', dataIndex: 'category' },
    { title: 'Description', dataIndex: 'description' },
    {
      title: 'Provider',
      render: () => effectiveProviderColumn
    },
    { title: 'Region', render: () => effectiveRegionColumn },
    {
      title: 'Price',
      width: 160,
      render: (_value, _record, index) => (
        <Input
          value={prices[String(index)] || ''}
          onChange={(e) =>
            setPrices((prev) => ({
              ...prev,
              [String(index)]: e.target.value
            }))
          }
        />
      )
    }
  ]

  if (!templates.length) {
    return (
      <Typography.Text type="secondary">
        No templates yet. Create one in the Templates tab first.
      </Typography.Text>
    )
  }

  return (
    <Space direction="vertical" style={{ width: '100%' }} size="middle">
      <Space direction="vertical" style={{ width: '100%' }} size="small">
        <Select
          value={templateId || undefined}
          style={{ width: 280 }}
          onChange={setTemplateId}
          placeholder="Select a template"
        >
          {templates.map((t) => (
            <Select.Option key={t.id} value={t.id}>
              {t.name}
            </Select.Option>
          ))}
        </Select>
        <Space wrap align="center">
          <Checkbox
            checked={providerLinked}
            onChange={(e) => handleProviderLinkChange(e.target.checked)}
          >
            Link provider key & column
          </Checkbox>
          {providerLinked ? (
            <Input
              value={providerKey}
              onChange={(e) => setProviderKey(e.target.value)}
              placeholder="Provider (key & column, e.g. aliyun)"
              style={{ width: 260 }}
            />
          ) : (
            <>
              <Input
                value={providerKey}
                onChange={(e) => setProviderKey(e.target.value)}
                placeholder="Provider key (unit_key, e.g. aliyun)"
                style={{ width: 240 }}
              />
              <Input
                value={providerColumn}
                onChange={(e) => setProviderColumn(e.target.value)}
                placeholder="Provider column (e.g. ALICLOUD)"
                style={{ width: 240 }}
              />
            </>
          )}
        </Space>
        <Space wrap align="center">
          <Checkbox
            checked={regionLinked}
            onChange={(e) => handleRegionLinkChange(e.target.checked)}
          >
            Link region key & column
          </Checkbox>
          {regionLinked ? (
            <Input
              value={regionKey}
              onChange={(e) => setRegionKey(e.target.value)}
              placeholder="Region (key & column, e.g. ap-southeast-1)"
              style={{ width: 260 }}
            />
          ) : (
            <>
              <Input
                value={regionKey}
                onChange={(e) => setRegionKey(e.target.value)}
                placeholder="Region key (unit_key, e.g. ap-southeast-1)"
                style={{ width: 240 }}
              />
              <Input
                value={regionColumn}
                onChange={(e) => setRegionColumn(e.target.value)}
                placeholder="Region column (e.g. ap-southeast-1)"
                style={{ width: 240 }}
              />
            </>
          )}
        </Space>
      </Space>

      <Table<UnitRow>
        columns={columns}
        dataSource={rows}
        rowKey={(_record, index) => String(index)}
        size="small"
        pagination={false}
      />

      <div>
        <Typography.Text strong>Generated CSV</Typography.Text>
        <Input.TextArea
          value={previewCsv}
          readOnly
          rows={6}
          style={{ fontFamily: 'monospace' }}
        />
      </div>

      <Space>
        <Button type="primary" loading={isImporting} onClick={handleImport}>
          Import to backend
        </Button>
        <Button
          disabled={!previewCsv}
          onClick={() =>
            triggerDownload(
              new Blob([previewCsv], { type: 'text/csv;charset=utf-8' }),
              'units-import.csv'
            )
          }
        >
          Download CSV
        </Button>
      </Space>
    </Space>
  )
}

const ExportTab = () => {
  const [groupId, setGroupId] = useState('')
  const [exporting, setExporting] = useState(false)

  const handleExport = async () => {
    setExporting(true)
    try {
      const params: { group_id?: number } = {}
      const gid = groupId.trim()
      if (gid) {
        const num = Number(gid)
        if (Number.isNaN(num)) {
          message.error('group_id must be a number.')
          return
        }
        params.group_id = num
      }
      const response = await getApiV1DevopsBillingProxyApiV1BillingUnitsExport(
        params
      )
      triggerDownload(response.data, 'units.csv')
      message.success('Export successful!')
    } catch (e: any) {
      message.error(e?.response?.data?.message || 'Export failed.')
    } finally {
      setExporting(false)
    }
  }

  return (
    <Space direction="vertical" style={{ width: '100%' }} size="middle">
      <Typography.Text type="secondary">
        Download units belonging to the SKU Group or matching its non-empty
        category as CSV. Group ID is optional; without it the CSV contains only
        a header.
      </Typography.Text>
      <Space>
        <Input
          value={groupId}
          onChange={(e) => setGroupId(e.target.value)}
          placeholder="group_id (optional)"
          style={{ width: 200 }}
        />
        <Button type="primary" loading={exporting} onClick={handleExport}>
          Download CSV
        </Button>
      </Space>
    </Space>
  )
}
