import { Button, Divider, Group, Paper, Stack, Table, Text, Textarea, Title } from '@pikku/mantine/core';
import { CandidateLifecycleNotifications } from '@heygermany/sdk';
import dayjs from 'dayjs';
import { useI18n } from '@/context/i18n-provider';
import { asI18n } from '@pikku/react';

type LifecycleNotificationsCardProps = {
  lifecycleNotifications?: CandidateLifecycleNotifications | null
  analysisIssuesDraft: string
  onAnalysisIssuesDraftChange: (value: string) => void
  onSaveAnalysisIssues: () => void
  isSaving: boolean
}

type ReminderCategory = 'initial' | 'invalid'
type ReminderType = 'day_1' | 'day_3' | 'day_6'

type ReminderRow = {
  type: ReminderType
  sentAt: string | null
  mailgunMessageId: string | null
  errorMessage: string | null
  lastErrorAt: string | null
}

const REMINDER_TYPES: ReminderRow[] = [
  { type: 'day_1', sentAt: null, mailgunMessageId: null, errorMessage: null, lastErrorAt: null },
  { type: 'day_3', sentAt: null, mailgunMessageId: null, errorMessage: null, lastErrorAt: null },
  { type: 'day_6', sentAt: null, mailgunMessageId: null, errorMessage: null, lastErrorAt: null },
]

const isPlainObject = (value: unknown): value is Record<string, unknown> =>
  typeof value === 'object' && value !== null && !Array.isArray(value)

const normalizeLifecycleNotifications = (value: unknown): CandidateLifecycleNotifications | null => {
  if (isPlainObject(value)) {
    return value as CandidateLifecycleNotifications
  }

  if (typeof value !== 'string') {
    return null
  }

  try {
    const parsedValue = JSON.parse(value)
    return isPlainObject(parsedValue) ? parsedValue as CandidateLifecycleNotifications : null
  } catch {
    return null
  }
}

const getString = (value: unknown) => {
  if (typeof value !== 'string') {
    return null
  }

  const normalizedValue = value.trim()
  return normalizedValue.length > 0 ? normalizedValue : null
}

const normalizeMessage = (value: string | null) => {
  if (!value) {
    return null
  }

  const normalizedValue = value.replace(/\s+/g, ' ').trim()
  return normalizedValue.length > 0 ? normalizedValue : null
}

const displayValue = (value: string | null) => value || '-'

const formatTimestamp = (value: string | null) => {
  if (!value) {
    return '-'
  }

  const parsedValue = dayjs(value)
  return parsedValue.isValid() ? parsedValue.format('YYYY-MM-DD HH:mm') : value
}

const getReminderKey = (category: ReminderCategory, type: ReminderType) =>
  `${category}.${type}`

const normalizeKey = (value: string) => value.toLowerCase().replace(/[_\-.]/g, '')

const getReminderValue = (
  lifecycleNotifications: CandidateLifecycleNotifications | null | undefined,
  category: ReminderCategory,
  type: ReminderType
) => {
  const directValue = lifecycleNotifications?.[getReminderKey(category, type)]

  if (directValue !== undefined) {
    return directValue
  }

  const normalizedReminderKey = normalizeKey(getReminderKey(category, type))

  return Object.entries(lifecycleNotifications ?? {}).find(([key]) => (
    normalizeKey(key) === normalizedReminderKey
  ))?.[1]
}

const getStringFromKeys = (record: Record<string, unknown>, keys: string[]) => {
  for (const key of keys) {
    const value = getString(record[key])

    if (value) {
      return value
    }
  }

  return null
}

const getReminderRows = (
  lifecycleNotifications: CandidateLifecycleNotifications | null | undefined,
  category: ReminderCategory
) =>
  REMINDER_TYPES.map((baseRow) => {
    const reminderValue = getReminderValue(lifecycleNotifications, category, baseRow.type)

    if (!isPlainObject(reminderValue)) {
      return baseRow
    }

    return {
      ...baseRow,
      sentAt: getStringFromKeys(reminderValue, ['sent_at', 'sentAt']),
      mailgunMessageId: getStringFromKeys(reminderValue, ['mailgun_message_id', 'mailgunMessageId']),
      errorMessage: normalizeMessage(getStringFromKeys(reminderValue, ['last_error', 'lastError'])),
      lastErrorAt: getStringFromKeys(reminderValue, ['last_error_at', 'lastErrorAt']),
    }
  })

const renderReminderSection = (
  title: string,
  rows: ReminderRow[]
) => (
  <Paper withBorder radius="sm" p="md">
    <Stack gap="xs">
      <Text fw={600}>{asI18n(title)}</Text>
      <div style={{ overflowX: 'auto' }}>
        <Table
          withTableBorder
          withColumnBorders={false}
          striped={false}
          highlightOnHover={false}
          style={{ tableLayout: 'fixed', minWidth: 980 }}
        >
          <Table.Thead>
            <Table.Tr>
              <Table.Th style={{ width: 120 }}>notification_type</Table.Th>
              <Table.Th style={{ width: 180 }}>sent_at</Table.Th>
              <Table.Th style={{ width: 280 }}>mailgun_message_id</Table.Th>
              <Table.Th>last_error</Table.Th>
              <Table.Th style={{ width: 180 }}>last_error_at</Table.Th>
            </Table.Tr>
          </Table.Thead>
          <Table.Tbody>
            {rows.map((row) => (
              <Table.Tr key={row.type}>
                <Table.Td style={{ verticalAlign: 'top' }}>
                  <Text size="sm" style={{ fontFamily: 'monospace' }}>
                    {asI18n(row.type)}
                  </Text>
                </Table.Td>
                <Table.Td style={{ verticalAlign: 'top' }}>
                  <Text size="sm" style={{ fontFamily: 'monospace', overflowWrap: 'anywhere' }}>
                    {asI18n(displayValue(row.sentAt) || '-')}
                  </Text>
                </Table.Td>
                <Table.Td style={{ verticalAlign: 'top' }}>
                  <Text size="sm" style={{ fontFamily: 'monospace', overflowWrap: 'anywhere' }}>
                    {asI18n(displayValue(row.mailgunMessageId) || '-')}
                  </Text>
                </Table.Td>
                <Table.Td style={{ verticalAlign: 'top' }}>
                  <Text size="sm" c={row.errorMessage ? 'red' : 'dimmed'} style={{ whiteSpace: 'normal', overflowWrap: 'anywhere', lineHeight: 1.4 }}>
                    {asI18n(displayValue(row.errorMessage) || '-')}
                  </Text>
                </Table.Td>
                <Table.Td style={{ verticalAlign: 'top' }}>
                  <Text size="sm" style={{ fontFamily: 'monospace', overflowWrap: 'anywhere' }}>
                    {asI18n(displayValue(row.lastErrorAt) || '-')}
                  </Text>
                </Table.Td>
              </Table.Tr>
            ))}
          </Table.Tbody>
        </Table>
      </div>
    </Stack>
  </Paper>
)

export const LifecycleNotificationsCard: React.FunctionComponent<LifecycleNotificationsCardProps> = ({
  lifecycleNotifications,
  analysisIssuesDraft,
  onAnalysisIssuesDraftChange,
  onSaveAnalysisIssues,
  isSaving,
}) => {
  const t = useI18n()
  const normalizedLifecycleNotifications = normalizeLifecycleNotifications(lifecycleNotifications)
  const initialRows = getReminderRows(normalizedLifecycleNotifications, 'initial')
  const invalidRows = getReminderRows(normalizedLifecycleNotifications, 'invalid')

  const analysisUpdatedAt =
    isPlainObject(normalizedLifecycleNotifications?.analysis)
      ? getString(normalizedLifecycleNotifications.analysis.updated_at ?? normalizedLifecycleNotifications.analysis.updatedAt)
      : null

  return (
    <Paper shadow="sm" p="lg" radius="md" withBorder mb="md">
      <Stack gap="md">
        <Stack gap={4}>
          <Title order={4}>{t('backoffice.lifecycle.title' as any)}</Title>
          <Text size="sm" c="dimmed">
            {t('backoffice.lifecycle.description' as any)}
          </Text>
        </Stack>

        {renderReminderSection(t('backoffice.lifecycle.initial' as any), initialRows)}
        {renderReminderSection(t('backoffice.lifecycle.invalid' as any), invalidRows)}

        <Divider />

        <Paper withBorder radius="sm" p="md">
          <Stack gap="sm">
            <Group justify="space-between" align="center">
              <Text fw={600}>{t('backoffice.lifecycle.customissues' as any)}</Text>
              {analysisUpdatedAt ? (
                <Group gap={4} wrap="nowrap">
                  <Text size="xs" c="dimmed">{t('backoffice.lifecycle.updated' as any)}</Text>
                  <Text size="xs" c="dimmed">{asI18n(formatTimestamp(analysisUpdatedAt))}</Text>
                </Group>
              ) : null}
            </Group>

            <Text size="sm" c="dimmed">
              {t('backoffice.lifecycle.helptext' as any)}
            </Text>
            <Textarea
              minRows={4}
              autosize
              value={analysisIssuesDraft}
              onChange={(event) => onAnalysisIssuesDraftChange(event.currentTarget.value)}
              placeholder={t('backoffice.lifecycle.placeholder' as any)}
            />
            <Group justify="flex-end">
              <Button
                variant="light"
                loading={isSaving}
                onClick={onSaveAnalysisIssues}
              >
                {t('backoffice.lifecycle.save' as any)}
              </Button>
            </Group>
          </Stack>
        </Paper>
      </Stack>
    </Paper>
  );
};
