import apiClient from './authApi';

export type PriorityUi = 'standard' | 'express';

export interface ApproverFormItem {
  email: string;
  name?: string;
  tat?: number | '';
  tatType?: 'hours' | 'days';
}

export interface ParticipantItem {
  id?: string;
  name: string;
  email: string;
}

export interface CreateWorkflowFromFormPayload {
  templateId?: string | null;
  templateType: 'CUSTOM' | 'TEMPLATE';
  title: string;
  description: string;
  priorityUi: PriorityUi;
  approverCount: number;
  approvers: ApproverFormItem[];
  spectators?: ParticipantItem[];
  ccList?: ParticipantItem[];
  isDraft?: boolean; // Added isDraft to the payload interface
}

// Utility to generate a RFC4122 v4 UUID (fallback if crypto.randomUUID not available)
function generateUuid(): string {
  if (typeof crypto !== 'undefined' && (crypto as any).randomUUID) {
    return (crypto as any).randomUUID();
  }
  // Fallback
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    const r = (Math.random() * 16) | 0;
    const v = c === 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

export interface CreateWorkflowResponse {
  id: string;
}

export async function createWorkflowFromForm(form: CreateWorkflowFromFormPayload): Promise<CreateWorkflowResponse> {
  // Map UI priority to API enum
  const priority = form.priorityUi.toUpperCase() === 'EXPRESS' ? 'EXPRESS' : 'STANDARD';

  // Build approval levels to match backend schema
  const approvalLevels = Array.from({ length: form.approverCount || 1 }, (_, i) => {
    const idx = i;
    const a = form.approvers[idx] || {} as ApproverFormItem;
    const levelNumber = idx + 1;
    const tatRaw = a.tat ?? '';
    let tatHours = 0;
    if (typeof tatRaw === 'number') {
      tatHours = a.tatType === 'days' ? tatRaw * 24 : tatRaw;
    }
    const approverEmail = a.email || '';
    const approverName = (a.name && a.name.trim()) || approverEmail.split('@')[0] || `Approver ${levelNumber}`;
    return {
      levelNumber,
      levelName: `Level ${levelNumber}`,
      approverId: generateUuid(),
      approverEmail,
      approverName,
      tatHours: tatHours > 0 ? tatHours : 24,
      isFinalApprover: levelNumber === (form.approverCount || 1),
    };
  });

  // Participants -> spectators and ccList
  const participants = [
    ...(form.spectators || []).map(p => ({
      userId: generateUuid(),
      userEmail: p.email,
      userName: p.name || p.email.split('@')[0] || 'Spectator',
      participantType: 'SPECTATOR' as const,
      canComment: true,
      canViewDocuments: true,
      canDownloadDocuments: false,
      notificationEnabled: true,
    })),
    ...(form.ccList || []).map(p => ({
      userId: generateUuid(),
      userEmail: p.email,
      userName: p.name || p.email.split('@')[0] || 'CC',
      participantType: 'CONSULTATION' as const,
      canComment: false,
      canViewDocuments: true,
      canDownloadDocuments: false,
      notificationEnabled: true,
    })),
  ];

  const payload = {
    templateType: form.templateType,
    title: form.title,
    description: form.description,
    priority, // STANDARD | EXPRESS
    approvalLevels,
    participants: participants.length ? participants : undefined,
    isDraft: form.isDraft, // Added isDraft to the payload
  };

  const res = await apiClient.post('/workflows', payload);
  const data = (res.data?.data || res.data) as any;
  return { id: data.id || data.workflowId || '' };
}

export async function createWorkflowMultipart(form: CreateWorkflowFromFormPayload, files: File[], category: 'SUPPORTING' | 'APPROVAL' | 'REFERENCE' | 'FINAL' | 'OTHER' = 'SUPPORTING') {
  // Simplified payload - backend handles user lookup and participant generation
  const payload: any = {
    templateType: form.templateType,
    title: form.title,
    description: form.description,
    priority: form.priorityUi.toUpperCase() === 'EXPRESS' ? 'EXPRESS' : 'STANDARD',
    isDraft: form.isDraft, // Added isDraft to the payload
    // Simplified approvers format - only email and tatHours required
    approvers: Array.from({ length: form.approverCount || 1 }, (_, i) => {
      const a = form.approvers[i] || ({} as any);
      const tat = typeof a.tat === 'number' ? a.tat : 0;

      if (!a.email || !a.email.trim()) {
        throw new Error(`Email is required for approver at level ${i + 1}.`);
      }

      return {
        email: a.email,
        tat: tat,
        tatType: a.tatType || 'hours',
      };
    }),
  };

  // Add spectators if any (simplified - only email required)
  if (form.spectators && form.spectators.length > 0) {
    payload.spectators = form.spectators
      .filter((s: any) => s?.email)
      .map((s: any) => ({ email: s.email }));
  }

  // Note: participants array is auto-generated by backend from approvers and spectators
  // No need to build or send it from frontend

  const formData = new FormData();
  formData.append('payload', JSON.stringify(payload));
  formData.append('category', category);
  files.forEach(f => formData.append('files', f));

  const res = await apiClient.post('/workflows/multipart', formData, {
    headers: { 'Content-Type': 'multipart/form-data' },
  });
  const data = res.data?.data || res.data;
  return { id: data?.requestId } as any;
}

export async function listWorkflows(params: {
  page?: number;
  limit?: number;
  search?: string;
  status?: string;
  priority?: string;
  templateType?: string;
  financialYear?: string;
  quarter?: string;
  department?: string;
  initiator?: string;
  approver?: string;
  slaCompliance?: string;
  dateRange?: string;
  startDate?: string;
  endDate?: string;
} = {}) {
  const {
    page = 1,
    limit = 20,
    search,
    status,
    priority,
    templateType,
    financialYear,
    quarter,
    department,
    initiator,
    approver,
    slaCompliance,
    dateRange,
    startDate,
    endDate,
  } = params;

  const res = await apiClient.get('/workflows', {
    params: {
      page,
      limit,
      search,
      status,
      priority,
      templateType,
      financialYear,
      quarter,
      department,
      initiator,
      approver,
      slaCompliance,
      dateRange,
      startDate,
      endDate,
    },
  });
  return res.data?.data || res.data;
}

// List requests where user is a participant (not initiator) - for regular users' "All Requests" page
// SEPARATE from listWorkflows (admin) to avoid interference
export async function listParticipantRequests(params: {
  page?: number;
  limit?: number;
  search?: string;
  status?: string;
  priority?: string;
  templateType?: string;
  financialYear?: string;
  quarter?: string;
  department?: string;
  initiator?: string;
  approver?: string;
  approverType?: string;
  slaCompliance?: string;
  dateRange?: string;
  startDate?: string;
  endDate?: string;
} = {}) {
  const {
    page = 1,
    limit = 20,
    search,
    status,
    priority,
    templateType,
    financialYear,
    quarter,
    department,
    initiator,
    approver,
    approverType,
    slaCompliance,
    dateRange,
    startDate,
    endDate,
  } = params;

  const res = await apiClient.get('/workflows/participant-requests', {
    params: {
      page,
      limit,
      search,
      status,
      priority,
      templateType,
      financialYear,
      quarter,
      department,
      initiator,
      approver,
      approverType,
      slaCompliance,
      dateRange,
      startDate,
      endDate,
    },
  });

  // Response structure: { success, data: { data: [...], pagination: {...} } }
  return {
    data: res.data?.data?.data || res.data?.data || [],
    pagination: res.data?.data?.pagination || { page, limit, total: 0, totalPages: 1 },
  };
}

// DEPRECATED: Use listParticipantRequests instead
// List requests where user is a participant (not initiator) - for "All Requests" page
export async function listMyWorkflows(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; department?: string; initiator?: string; approver?: string; slaCompliance?: string; dateRange?: string; startDate?: string; endDate?: string } = {}) {
  const { page = 1, limit = 20, search, status, priority, department, initiator, approver, slaCompliance, dateRange, startDate, endDate } = params;
  const res = await apiClient.get('/workflows/my', {
    params: {
      page,
      limit,
      search,
      status,
      priority,
      department,
      initiator,
      approver,
      slaCompliance,
      dateRange,
      startDate,
      endDate
    }
  });
  // Response structure: { success, data: { data: [...], pagination: {...} } }
  return {
    data: res.data?.data?.data || res.data?.data || [],
    pagination: res.data?.data?.pagination || { page, limit, total: 0, totalPages: 1 }
  };
}

// List requests where user is the initiator - for "My Requests" page
export async function listMyInitiatedWorkflows(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; templateType?: string; department?: string; slaCompliance?: string; dateRange?: string; startDate?: string; endDate?: string } = {}) {
  const { page = 1, limit = 20, search, status, priority, templateType, department, slaCompliance, dateRange, startDate, endDate } = params;
  const res = await apiClient.get('/workflows/my-initiated', {
    params: {
      page,
      limit,
      search,
      status,
      priority,
      templateType,
      department,
      slaCompliance,
      dateRange,
      startDate,
      endDate
    }
  });
  // Response structure: { success, data: { data: [...], pagination: {...} } }
  return {
    data: res.data?.data?.data || res.data?.data || [],
    pagination: res.data?.data?.pagination || { page, limit, total: 0, totalPages: 1 }
  };
}

export async function listOpenForMe(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; templateType?: string; financialYear?: string; quarter?: string; sortBy?: string; sortOrder?: string } = {}) {
  const { page = 1, limit = 20, search, status, priority, templateType, financialYear, quarter, sortBy, sortOrder } = params;
  const res = await apiClient.get('/workflows/open-for-me', { params: { page, limit, search, status, priority, templateType, financialYear, quarter, sortBy, sortOrder } });
  // Response structure: { success, data: { data: [...], pagination: {...} } }
  return {
    data: res.data?.data?.data || res.data?.data || [],
    pagination: res.data?.data?.pagination || { page, limit, total: 0, totalPages: 1 }
  };
}

export async function listClosedByMe(params: { page?: number; limit?: number; search?: string; status?: string; priority?: string; templateType?: string; financialYear?: string; quarter?: string; sortBy?: string; sortOrder?: string } = {}) {
  const { page = 1, limit = 20, search, status, priority, templateType, financialYear, quarter, sortBy, sortOrder } = params;
  const res = await apiClient.get('/workflows/closed-by-me', { params: { page, limit, search, status, priority, templateType, financialYear, quarter, sortBy, sortOrder } });
  // Response structure: { success, data: { data: [...], pagination: {...} } }
  return {
    data: res.data?.data?.data || res.data?.data || [],
    pagination: res.data?.data?.pagination || { page, limit, total: 0, totalPages: 1 }
  };
}

export async function getWorkflowDetails(requestId: string, _workflowType?: string) {
  const res = await apiClient.get(`/workflows/${requestId}/details`);
  return res.data?.data || res.data;
}

export async function getWorkNotes(requestId: string) {
  const res = await apiClient.get(`/workflows/${requestId}/work-notes`);
  return res.data?.data || res.data;
}

export async function createWorkNoteMultipart(requestId: string, payload: any, files: File[] = []) {
  const formData = new FormData();
  formData.append('payload', JSON.stringify(payload || {}));
  files.forEach(f => formData.append('files', f));
  const res = await apiClient.post(`/workflows/${requestId}/work-notes`, formData, {
    headers: { 'Content-Type': 'multipart/form-data' },
  });
  return res.data?.data || res.data;
}

export async function addApprover(requestId: string, email: string) {
  const res = await apiClient.post(`/workflows/${requestId}/participants/approver`, { email });
  return res.data?.data || res.data;
}

export async function addApproverAtLevel(
  requestId: string,
  email: string,
  tatHours: number,
  level: number
) {
  const res = await apiClient.post(`/workflows/${requestId}/approvers/at-level`, {
    email,
    tatHours,
    level
  });
  return res.data?.data || res.data;
}

export async function skipApprover(requestId: string, levelId: string, reason?: string) {
  const res = await apiClient.post(`/workflows/${requestId}/approvals/${levelId}/skip`, {
    reason
  });
  return res.data?.data || res.data;
}

export async function addSpectator(requestId: string, email: string) {
  const res = await apiClient.post(`/workflows/${requestId}/participants/spectator`, { email });
  return res.data?.data || res.data;
}

export async function pauseWorkflow(
  requestId: string,
  levelId: string | null,
  reason: string,
  resumeDate: Date
) {
  const res = await apiClient.post(`/workflows/${requestId}/pause`, {
    levelId,
    reason,
    resumeDate: resumeDate.toISOString()
  });
  return res.data?.data || res.data;
}

export async function resumeWorkflow(requestId: string, notes?: string) {
  const res = await apiClient.post(`/workflows/${requestId}/resume`, { notes });
  return res.data?.data || res.data;
}

export async function retriggerPause(requestId: string) {
  const res = await apiClient.post(`/workflows/${requestId}/pause/retrigger`);
  return res.data?.data || res.data;
}

export async function getPauseDetails(requestId: string) {
  const res = await apiClient.get(`/workflows/${requestId}/pause`);
  return res.data?.data || res.data;
}

export function getWorkNoteAttachmentPreviewUrl(attachmentId: string): string {
  const baseURL = import.meta.env.VITE_BASE_URL || '';
  return `${baseURL}/api/v1/workflows/work-notes/attachments/${attachmentId}/preview`;
}

export function getDocumentPreviewUrl(documentId: string): string {
  const baseURL = import.meta.env.VITE_BASE_URL || '';
  return `${baseURL}/api/v1/workflows/documents/${documentId}/preview`;
}

/**
 * Extract filename from Content-Disposition header
 * Handles both formats: filename="name" and filename*=UTF-8''encoded
 */
function extractFilenameFromContentDisposition(contentDisposition: string | null): string {
  if (!contentDisposition) {
    return 'download';
  }

  // Try to extract from filename* first (RFC 5987 encoded) - preferred for non-ASCII
  const filenameStarMatch = contentDisposition.match(/filename\*=UTF-8''([^;]+)/);
  if (filenameStarMatch && filenameStarMatch[1]) {
    try {
      return decodeURIComponent(filenameStarMatch[1]);
    } catch {
      // If decoding fails, fall back to regular filename
    }
  }

  // Fallback to regular filename (for ASCII-only filenames)
  const filenameMatch = contentDisposition.match(/filename="?([^";]+)"?/);
  if (filenameMatch && filenameMatch.length > 1 && filenameMatch[1]) {
    // Remove quotes and extract only the filename part (before any semicolon)
    const filenameValue: string = filenameMatch[1];
    const parts = filenameValue.replace(/^"|"$/g, '').split(';');
    const extracted = parts[0]?.trim();
    return extracted || 'download';
  }

  return 'download';
}

export async function downloadDocument(documentId: string): Promise<void> {
  const baseURL = import.meta.env.VITE_BASE_URL || '';
  const downloadUrl = `${baseURL}/api/v1/workflows/documents/${documentId}/download`;
  const isProduction = import.meta.env.PROD || import.meta.env.MODE === 'production';

  try {
    // Build fetch options
    const fetchOptions: RequestInit = {
      credentials: 'include', // Send cookies in production
    };

    // In development, add Authorization header from localStorage
    if (!isProduction) {
      const token = localStorage.getItem('accessToken');
      fetchOptions.headers = {
        'Authorization': `Bearer ${token}`
      };
    }

    const response = await fetch(downloadUrl, fetchOptions);

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(`Download failed: ${response.status} - ${errorText}`);
    }

    const blob = await response.blob();
    const url = window.URL.createObjectURL(blob);

    const contentDisposition = response.headers.get('Content-Disposition');
    const filename = extractFilenameFromContentDisposition(contentDisposition);

    const downloadLink = document.createElement('a');
    downloadLink.href = url;
    downloadLink.download = filename;
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
    window.URL.revokeObjectURL(url);
  } catch (error) {
    console.error('[Download] Failed:', error);
    throw error;
  }
}

export async function downloadWorkNoteAttachment(attachmentId: string): Promise<void> {
  const downloadBaseURL = import.meta.env.VITE_BASE_URL || '';
  const downloadUrl = `${downloadBaseURL}/api/v1/workflows/work-notes/attachments/${attachmentId}/download`;
  const isProduction = import.meta.env.PROD || import.meta.env.MODE === 'production';

  try {
    // Build fetch options
    const fetchOptions: RequestInit = {
      credentials: 'include', // Send cookies in production
    };

    // In development, add Authorization header from localStorage
    if (!isProduction) {
      const token = localStorage.getItem('accessToken');
      fetchOptions.headers = {
        'Authorization': `Bearer ${token}`
      };
    }

    const response = await fetch(downloadUrl, fetchOptions);

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(`Download failed: ${response.status} - ${errorText}`);
    }

    const blob = await response.blob();
    const url = window.URL.createObjectURL(blob);

    // Get filename from Content-Disposition header or use default
    const contentDisposition = response.headers.get('Content-Disposition');
    const filename = extractFilenameFromContentDisposition(contentDisposition);

    const downloadLink = document.createElement('a');
    downloadLink.href = url;
    downloadLink.download = filename;
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
    window.URL.revokeObjectURL(url);
  } catch (error) {
    console.error('[Download] Failed:', error);
    throw error;
  }
}

export default {
  createWorkflowFromForm,
  createWorkflowMultipart,
  listWorkflows, // Admin: All organization requests
  listParticipantRequests, // Regular users: Participant requests only (not initiator)
  listMyWorkflows, // DEPRECATED: Use listParticipantRequests
  listMyInitiatedWorkflows, // Regular users: Initiator requests only
  listOpenForMe,
  listClosedByMe,
  submitWorkflow,
  getWorkflowDetails,
  getWorkNotes,
  createWorkNoteMultipart,
  handleInitiatorAction,
};

export async function submitWorkflow(requestId: string) {
  const res = await apiClient.patch(`/workflows/${requestId}/submit`);
  return res.data?.data || res.data;
}

export async function updateWorkflow(requestId: string, updateData: any) {
  const res = await apiClient.put(`/workflows/${requestId}`, updateData);
  return res.data?.data || res.data;
}

export async function updateWorkflowMultipart(requestId: string, updateData: any, files?: File[], deleteDocumentIds?: string[]) {
  const payload = {
    ...updateData,
    deleteDocumentIds: deleteDocumentIds || []
  };

  const formData = new FormData();
  formData.append('payload', JSON.stringify(payload));
  formData.append('category', 'SUPPORTING');
  if (files && files.length > 0) {
    files.forEach(f => formData.append('files', f));
  }

  const res = await apiClient.put(`/workflows/${requestId}/multipart`, formData, {
    headers: { 'Content-Type': 'multipart/form-data' },
  });
  return res.data?.data || res.data;
}

export async function approveLevel(requestId: string, levelId: string, comments?: string) {
  const res = await apiClient.patch(`/workflows/${requestId}/approvals/${levelId}/approve`, {
    action: 'APPROVE',
    comments: comments || ''
  });
  return res.data?.data || res.data;
}

export async function rejectLevel(requestId: string, levelId: string, rejectionReason?: string, comments?: string) {
  const res = await apiClient.patch(`/workflows/${requestId}/approvals/${levelId}/reject`, {
    action: 'REJECT',
    rejectionReason: rejectionReason || '',
    comments: comments || ''
  });
  return res.data?.data || res.data;
}

export async function updateAndSubmitWorkflow(requestId: string, workflowData: CreateWorkflowFromFormPayload, _files?: File[]) {
  // First update the workflow
  const payload: any = {
    title: workflowData.title,
    description: workflowData.description,
    priority: workflowData.priorityUi.toUpperCase() === 'EXPRESS' ? 'EXPRESS' : 'STANDARD',
  };

  // Update workflow details
  await apiClient.put(`/workflows/${requestId}`, payload);

  // If files provided, update documents (this would need backend support for updating documents)
  // For now, we'll just submit the updated workflow
  const res = await apiClient.patch(`/workflows/${requestId}/submit`);
  return res.data?.data || res.data;
}

/**
 * Update breach reason for a TAT alert
 */
export async function updateBreachReason(levelId: string, breachReason: string): Promise<void> {
  const response = await apiClient.put(`/tat/breach-reason/${levelId}`, {
    breachReason
  });

  if (!response.data.success) {
    throw new Error(response.data.error || 'Failed to update breach reason');
  }
}

/**
 * Handle initiator action on returned (rejected without closure) requests
 * POST /api/v1/workflows/:id/initiator-action
 */
export async function handleInitiatorAction(
  requestId: string,
  action: 'REOPEN' | 'DISCUSS' | 'REVISE' | 'CANCEL',
  data?: any
): Promise<any> {
  const response = await apiClient.post(`/workflows/${requestId}/initiator-action`, {
    action,
    ...data
  });
  return response.data?.data || response.data;
}
/**
 * Get version history for a workflow request
 * GET /api/v1/workflows/:id/history
 */
export async function getWorkflowHistory(requestId: string): Promise<any[]> {
  const response = await apiClient.get(`/workflows/${requestId}/history`);
  return response.data?.data || [];
}
