/**
 * Mail plugin API client.
 *
 * All requests use the shared `apiClient` (`baseURL: '/api/v1'`) and target the
 * Mail plugin routes under `/mail/...`.
 */

import { apiClient, apiDelete, apiGet, apiPatch, apiPost } from './client';

// ─── Types ─────────────────────────────────────────────────────────────────

export interface MailAccount {
  id: string;
  email: string;
  display_name: string;
  imap_host: string;
  imap_port: number;
  smtp_host: string;
  smtp_port: number;
  is_shared: boolean;
  is_active: boolean;
  sent_folder_imap_name?: string | null;
  drafts_folder_imap_name?: string | null;
  spam_folder_imap_name?: string | null;
  trash_folder_imap_name?: string | null;
  created_at?: string | null;
  updated_at?: string | null;
}

export interface MailFolder {
  id: string;
  account_id: string;
  name: string;
  imap_name?: string;
  parent_id: string | null;
  unread_count: number;
  total_count: number;
  children?: MailFolder[];
}

export interface MailAttachment {
  id: string;
  mail_id: string;
  filename: string;
  mime_type: string;
  size_bytes: number;
  size: number;
  content_id?: string | null;
  is_inline: boolean;
  dms_file_id?: string | null;
}

export interface Mail {
  id: string;
  folder_id: string; account_id: string;
  from_address: string;
  from_name: string;
  to_addresses: string[];
  cc_addresses: string[];
  bcc_addresses: string[];
  subject: string;
  body_text: string;
  body_html: string | null;
  sanitized_html: string | null;
  date: string;
  is_seen: boolean;
  is_flagged: boolean;
  flag_type?: string | null;
  is_draft: boolean;
  is_answered: boolean;
  has_attachments: boolean;
  attachments?: MailAttachment[];
  labels?: MailLabel[];
  thread_id?: string | null;
  in_reply_to?: string | null;
  message_id?: string | null;
}

export interface MailListResult {
  mails: Mail[];
  total: number;
  page: number;
  page_size: number;
}

export interface MailTemplate {
  id: string;
  name: string;
  subject: string;
  body: string;
  variables: string[];
  created_at?: string | null;
  updated_at?: string | null;
}

export interface MailSignature {
  id: string;
  name: string;
  body_html: string;
  is_default: boolean;
  created_at?: string | null;
  updated_at?: string | null;
}

export type RuleConditionType = 'from_contains' | 'to_contains' | 'subject_contains' | 'has_attachment' | 'body_contains';
export type RuleActionType = 'move_to_folder' | 'mark_as_read' | 'mark_as_flagged' | 'forward_to' | 'delete';

export interface RuleCondition {
  type: RuleConditionType;
  value: string;
}

export interface RuleAction {
  type: RuleActionType;
  value: string;
}

export interface MailRule {
  id: string;
  name: string;
  account_id: string;
  priority: number;
  is_active: boolean;
  conditions: RuleCondition[];
  actions: RuleAction[];
  created_at?: string | null;
  updated_at?: string | null;
}

export interface MailLabel {
  id: string;
  name: string;
  color: string;
  created_at?: string | null;
}

export interface PgpKey {
  id: string;
  key_id: string;
  fingerprint: string;
  user_id: string;
  is_private: boolean;
  expires_at: string | null;
  created_at?: string | null;
}

export interface ContactPgpKey {
  contact_id: string;
  contact_name: string;
  key_id: string;
  fingerprint: string;
  added_at: string;
}

export interface VacationConfig {
  enabled: boolean;
  start_date: string | null;
  end_date: string | null;
  subject: string;
  body: string;
  dedup_days: number;
}

export interface SharedMailboxUser {
  user_id: string;
  user_name: string;
  permissions: string[];
}

export interface DelegateAccess {
  id: string;
  delegate_user_id: string;
  delegate_user_name: string;
  permissions: string[];
  folder_ids: string[];
}

export interface SendPermission {
  id: string;
  grantee_user_id: string;
  grantee_user_name: string;
  from_address: string;
}

export interface ThreadResult {
  thread_id: string;
  subject: string;
  mails: Mail[];
}

// ─── Payloads ──────────────────────────────────────────────────────────────

export interface CreateAccountPayload {
  email: string;
  display_name: string;
  imap_host: string;
  imap_port: number;
  smtp_host: string;
  smtp_port: number;
  username?: string;
  password: string;
  is_shared?: boolean;
  sent_folder_imap_name?: string | null;
  drafts_folder_imap_name?: string | null;
  spam_folder_imap_name?: string | null;
  trash_folder_imap_name?: string | null;
}

export interface UpdateAccountPayload {
  display_name?: string;
  imap_host?: string;
  imap_port?: number;
  smtp_host?: string;
  smtp_port?: number;
  password?: string;
  is_active?: boolean;
  sent_folder_imap_name?: string | null;
  drafts_folder_imap_name?: string | null;
  spam_folder_imap_name?: string | null;
  trash_folder_imap_name?: string | null;
}

export interface CreateFolderPayload {
  account_id: string;
  name: string;
  parent_id?: string | null;
}

export interface UpdateFolderPayload {
  name?: string;
  parent_id?: string | null;
}

export interface SendMailPayload {
  account_id: string;
  to: string[];
  cc?: string[];
  bcc?: string[];
  subject: string;
  body: string;
  is_html: boolean;
  in_reply_to?: string | null;
  attachments?: string[];
  signature_id?: string | null;
}

export interface ReplyPayload {
  account_id: string;
  body: string;
  is_html: boolean;
  to?: string[];
  cc?: string[];
  signature_id?: string | null;
}

export interface ForwardPayload {
  account_id: string;
  to: string[];
  body?: string;
  is_html: boolean;
  signature_id?: string | null;
}

export interface FlagUpdatePayload {
  is_seen?: boolean;
  is_flagged?: boolean;
  flag_type?: string | null;
  is_draft?: boolean;
  is_answered?: boolean;
  is_forwarded?: boolean;
}

export interface LinkMailPayload {
  contact_id?: string | null;
}

export interface CreateEventFromMailPayload {
  title: string;
  start: string;
  end: string;
  description?: string;
  location?: string;
  calendar_id?: string;
}

export interface AssignLabelPayload {
  label_id: string;
}

export interface CreateTemplatePayload {
  name: string;
  subject: string;
  body: string;
  variables?: string[];
}

export interface SubstituteTemplatePayload {
  template_id: string;
  variables: Record<string, string>;
}

export interface SubstituteResult {
  subject: string;
  body: string;
}

export interface CreateSignaturePayload {
  name: string;
  body_html: string;
  is_default?: boolean;
}

export interface CreateRulePayload {
  name: string;
  account_id: string;
  priority: number;
  is_active: boolean;
  conditions: RuleCondition[];
  actions: RuleAction[];
}

export interface CreateLabelPayload {
  name: string;
  color: string;
}

export interface VacationPayload {
  enabled: boolean;
  start_date: string | null;
  end_date: string | null;
  subject: string;
  body: string;
  dedup_days?: number;
}

export interface ImportPgpKeyPayload {
  private_key: string;
  passphrase?: string;
}

export interface StoreContactPgpKeyPayload {
  public_key: string;
}

export interface AssignSharedMailboxUsersPayload {
  user_ids: string[];
  permissions: string[];
}

export interface CreateDelegatePayload {
  delegate_user_id: string;
  permissions: string[];
  folder_ids: string[];
}

export interface GrantSendPermissionPayload {
  grantee_user_id: string;
  from_address: string;
}

// ─── Accounts ──────────────────────────────────────────────────────────────

export function fetchAccounts(): Promise<MailAccount[]> {
  return apiGet<MailAccount[]>('/mail/accounts');
}

export function createAccount(payload: CreateAccountPayload): Promise<MailAccount> {
  return apiPost<MailAccount>('/mail/accounts', payload);
}

export function updateAccount(accountId: string, payload: UpdateAccountPayload): Promise<MailAccount> {
  return apiPatch<MailAccount>(`/mail/accounts/${accountId}`, payload);
}

export function deleteAccount(accountId: string): Promise<void> {
  return apiDelete<void>(`/mail/accounts/${accountId}`);
}

export function fetchSharedAccounts(): Promise<MailAccount[]> {
  return apiGet<MailAccount[]>('/mail/accounts/shared');
}

export function assignSharedMailboxUsers(accountId: string, payload: AssignSharedMailboxUsersPayload): Promise<void> {
  return apiPost<void>(`/mail/accounts/${accountId}/users`, payload);
}

export function createDelegate(accountId: string, payload: CreateDelegatePayload): Promise<DelegateAccess> {
  return apiPost<DelegateAccess>(`/mail/accounts/${accountId}/delegates`, payload);
}

export function grantSendPermission(accountId: string, payload: GrantSendPermissionPayload): Promise<SendPermission> {
  return apiPost<SendPermission>(`/mail/accounts/${accountId}/send-permissions`, payload);
}

export function testConnection(accountId: string): Promise<{ success: boolean; message: string }> {
  return apiPost<{ success: boolean; message: string }>(`/mail/accounts/${accountId}/test-connection`);
}

export function triggerSync(accountId: string): Promise<{ synced: number; error?: string }> {
  return apiPost<{ synced: number; error?: string }>(`/mail/accounts/${accountId}/sync`);
}

/**
 * Decode MIME encoded-words (=?UTF-8?Q?...?=) to readable text.
 * Used for mail subjects/from names that were stored before backend decoding was added.
 */
export function decodeMimeHeader(value: string | undefined | null): string {
  if (!value) return '';
  // Check if value contains MIME encoded-words
  if (!value.includes('=?')) return value;
  try {
    // Decode all encoded-words in the string
    return value.replace(/=\?([^?]+)\?([BQ])\?([^?]*)\?=/gi, (_match, _charset, encoding, encoded) => {
      try {
        if (encoding.toUpperCase() === 'B') {
          // Base64 decode
          const decoded = atob(encoded);
          return decodeURIComponent(escape(decoded));
        } else {
          // Q encoding: replace _ with space, then decode =XX hex sequences
          const qDecoded = encoded.replace(/_/g, ' ').replace(/=([0-9A-F]{2})/gi, (_m: string, hex: string) => {
            return String.fromCharCode(parseInt(hex, 16));
          });
          return decodeURIComponent(escape(qDecoded));
        }
      } catch {
        return _match;
      }
    });
  } catch {
    return value;
  }
}

/**
 * Replace placeholder variables in signature HTML with actual user/tenant data.
 * Variables: {{user.name}}, {{user.first_name}}, {{user.last_name}},
 * {{user.email}}, {{user.role}}, {{tenant.name}}, {{date}}
 */
import { formatDateShort } from '@/utils/date';

export function replaceSignatureVariables(
  html: string,
  user: { name?: string; email?: string; role?: string; first_name?: string; last_name?: string },
  tenant?: { name?: string },
): string {
  const dateStr = formatDateShort(new Date());
  const firstName = user.first_name || (user.name ? user.name.split(' ')[0] : '');
  const lastName = user.last_name || (user.name ? user.name.split(' ').slice(1).join(' ') : '');

  return html
    .replace(/\{\{user\.name\}\}/gi, user.name || '')
    .replace(/\{\{user\.first_name\}\}/gi, firstName)
    .replace(/\{\{user\.last_name\}\}/gi, lastName)
    .replace(/\{\{user\.email\}\}/gi, user.email || '')
    .replace(/\{\{user\.role\}\}/gi, user.role || '')
    .replace(/\{\{tenant\.name\}\}/gi, tenant?.name || '')
    .replace(/\{\{date\}\}/gi, dateStr);
}

// ─── Folders ────────────────────────────────────────────────────────────────

export function fetchFolders(accountId: string): Promise<MailFolder[]> {
  const qs = new URLSearchParams({ account_id: accountId }).toString();
  return apiGet<MailFolder[]>(`/mail/folders?${qs}`);
}

export function createFolder(payload: CreateFolderPayload): Promise<MailFolder> {
  return apiPost<MailFolder>('/mail/folders', payload);
}

export function updateFolder(folderId: string, payload: UpdateFolderPayload): Promise<MailFolder> {
  return apiPatch<MailFolder>(`/mail/folders/${folderId}`, payload);
}

export function deleteFolder(folderId: string): Promise<void> {
  return apiDelete<void>(`/mail/folders/${folderId}`);
}

export function emptyFolder(folderId: string): Promise<{ emptied_count: number }> {
  return apiPost<{ emptied_count: number }>(`/mail/folders/${folderId}/empty`, {});
}

export function syncFolder(folderId: string): Promise<{ synced: number; error?: string }> {
  return apiPost<{ synced: number; error?: string }>(`/mail/folders/${folderId}/sync`, {});
}

// ─── Mails ──────────────────────────────────────────────────────────────────

export function fetchMails(folderId: string, page: number, sortBy?: string, sortOrder?: string): Promise<MailListResult> {
  const params = new URLSearchParams({ folder_id: folderId, page: String(page) });
  if (sortBy) params.set('sort_by', sortBy);
  if (sortOrder) params.set('sort_order', sortOrder);
  return apiGet<MailListResult>(`/mail?${params.toString()}`);
}

export function getMail(mailId: string): Promise<Mail> {
  return apiGet<Mail>(`/mail/${mailId}`);
}

export function sendMail(payload: SendMailPayload): Promise<{ id: string; success: boolean }> {
  return apiPost<{ id: string; success: boolean }>('/mail/send', payload);
}

export function replyMail(mailId: string, payload: ReplyPayload): Promise<{ id: string; success: boolean }> {
  return apiPost<{ id: string; success: boolean }>(`/mail/${mailId}/reply`, payload);
}

export function forwardMail(mailId: string, payload: ForwardPayload): Promise<{ id: string; success: boolean }> {
  return apiPost<{ id: string; success: boolean }>(`/mail/${mailId}/forward`, payload);
}

export function updateFlags(mailId: string, payload: FlagUpdatePayload): Promise<void> {
  return apiPatch<void>(`/mail/${mailId}/flags`, payload);
}

export function linkMail(mailId: string, payload: LinkMailPayload): Promise<void> {
  return apiPost<void>(`/mail/${mailId}/link`, payload);
}

export function createEventFromMail(mailId: string, payload: CreateEventFromMailPayload): Promise<{ id: string; success: boolean }> {
  return apiPost<{ id: string; success: boolean }>(`/mail/${mailId}/create-event`, payload);
}

export function assignLabel(mailId: string, payload: AssignLabelPayload): Promise<void> {
  return apiPost<void>(`/mail/${mailId}/labels`, payload);
}

// ─── Search & Threads ──────────────────────────────────────────────────────

export function searchMails(query: string): Promise<MailListResult> {
  const qs = new URLSearchParams({ q: query }).toString();
  return apiGet<MailListResult>(`/mail/search?${qs}`);
}

export function fetchThreads(accountId: string): Promise<ThreadResult[]> {
  const qs = new URLSearchParams({ account_id: accountId }).toString();
  return apiGet<ThreadResult[]>(`/mail/threads?${qs}`);
}

// ─── Attachments ─────────────────────────────────────────────────────────────

export function getAttachmentDownloadUrl(mailId: string, attachmentId: string): string {
  return `/api/v1/mail/${mailId}/attachments/${attachmentId}`;
}

export function downloadAttachment(mailId: string, attachmentId: string): Promise<Blob> {
  return apiClient.get<Blob>(`/mail/${mailId}/attachments/${attachmentId}`, {
    responseType: 'blob',
  }).then((res) => res.data);
}

export interface UploadedAttachment {
  id: string;
  filename: string;
  mime_type: string;
  size_bytes: number;
  path: string;
}

export function uploadAttachment(file: File): Promise<UploadedAttachment> {
  const formData = new FormData();
  formData.append('file', file);
  return apiClient.post<UploadedAttachment>('/mail/upload-attachment', formData, {
    headers: { 'Content-Type': 'multipart/form-data' },
  }).then((res) => res.data);
}

// ─── Templates ──────────────────────────────────────────────────────────────

export function createTemplate(payload: CreateTemplatePayload): Promise<MailTemplate> {
  return apiPost<MailTemplate>('/mail/templates', payload);
}

export function fetchTemplates(): Promise<MailTemplate[]> {
  return apiGet<MailTemplate[]>('/mail/templates');
}

export function substituteTemplate(payload: SubstituteTemplatePayload): Promise<SubstituteResult> {
  return apiPost<SubstituteResult>('/mail/templates/substitute', payload);
}

// ─── Signatures ──────────────────────────────────────────────────────────────

export function createSignature(payload: CreateSignaturePayload): Promise<MailSignature> {
  return apiPost<MailSignature>('/mail/signatures', payload);
}

export function fetchSignatures(): Promise<MailSignature[]> {
  return apiGet<MailSignature[]>('/mail/signatures');
}

export function deleteSignature(signatureId: string): Promise<void> {
  return apiDelete<void>(`/mail/signatures/${signatureId}`);
}

export function updateSignature(signatureId: string, payload: Partial<CreateSignaturePayload>): Promise<MailSignature> {
  return apiPatch<MailSignature>(`/mail/signatures/${signatureId}`, payload);
}

// ─── Rules ───────────────────────────────────────────────────────────────────

export function createRule(payload: CreateRulePayload): Promise<MailRule> {
  return apiPost<MailRule>('/mail/rules', payload);
}

export function fetchRules(): Promise<MailRule[]> {
  return apiGet<MailRule[]>('/mail/rules');
}

export function deleteRule(ruleId: string): Promise<void> {
  return apiDelete<void>(`/mail/rules/${ruleId}`);
}

// ─── Vacation ─────────────────────────────────────────────────────────────────

export function configureVacation(payload: VacationPayload): Promise<{ success: boolean }> {
  return apiPost<{ success: boolean }>('/mail/vacation', payload);
}

export function testVacationDedup(): Promise<{ dedup_count: number }> {
  return apiPost<{ dedup_count: number }>('/mail/vacation/test-dedup');
}

// ─── PGP ──────────────────────────────────────────────────────────────────────

export function importPgpKey(payload: ImportPgpKeyPayload): Promise<PgpKey> {
  return apiPost<PgpKey>('/mail/pgp/keys', payload);
}

export function fetchPgpKeys(): Promise<PgpKey[]> {
  return apiGet<PgpKey[]>('/mail/pgp/keys');
}

export function encryptMessage(payload: { recipient_key_id: string; message: string }): Promise<{ encrypted: string }> {
  return apiPost<{ encrypted: string }>('/mail/pgp/encrypt', payload);
}

export function storeContactPgpKey(contactId: string, payload: StoreContactPgpKeyPayload): Promise<void> {
  return apiPost<void>(`/mail/contacts/${contactId}/pgp-key`, payload);
}

export function fetchContactPgpKeys(): Promise<ContactPgpKey[]> {
  return apiGet<ContactPgpKey[]>('/mail/contacts/pgp-keys');
}

// ─── Labels ───────────────────────────────────────────────────────────────────

export function createLabel(payload: CreateLabelPayload): Promise<MailLabel> {
  return apiPost<MailLabel>('/mail/labels', payload);
}

export function fetchLabels(): Promise<MailLabel[]> {
  return apiGet<MailLabel[]>('/mail/labels');
}

export function deleteLabel(labelId: string): Promise<void> {
  return apiDelete<void>(`/mail/labels/${labelId}`);
}

// ─── Delete / Move / Drafts ──────────────────────────────────────────────────

export function deleteMail(mailId: string): Promise<void> {
  return apiDelete<void>(`/mail/${mailId}`);
}

export function moveMail(mailId: string, targetFolderId: string): Promise<Mail> {
  return apiPost<Mail>(`/mail/${mailId}/move`, { target_folder_id: targetFolderId });
}

export interface MailDraftPayload {
  account_id: string;
  to: string[];
  cc: string[];
  bcc: string[];
  subject: string;
  body_text: string;
  body_html: string;
}

export function saveDraft(payload: MailDraftPayload): Promise<Mail> {
  return apiPost<Mail>('/mail/drafts', payload);
}

export function updateDraft(mailId: string, payload: MailDraftPayload): Promise<Mail> {
  return apiPatch<Mail>(`/mail/drafts/${mailId}`, payload);
}
