export interface ImportEntry {
  project_name: string
  client_name?: string
  task_name?: string
  description?: string
  start_time: string
  end_time?: string
  duration: number
  tags?: string[]
}

export type DateFormat = 'DMY' | 'MDY'
export type DateDetectResult = DateFormat | 'ambiguous'

export function detectDateFormat(rows: string[][], dateColIndex: number): DateDetectResult {
  if (dateColIndex < 0) return 'ambiguous'
  for (let i = 1; i < rows.length; i++) {
    const val = (rows[i]?.[dateColIndex] || '').trim()
    const match = val.match(/^(\d{1,2})[\/.](\d{1,2})[\/.](\d{2,4})$/)
    if (!match) continue
    const a = parseInt(match[1])
    const b = parseInt(match[2])
    if (a > 12) return 'DMY'
    if (b > 12) return 'MDY'
  }
  return 'ambiguous'
}

export function parseCSV(text: string): string[][] {
  const lines = text.split('\n').filter(l => l.trim())
  return lines.map(line => {
    const cells: string[] = []
    let current = ''
    let inQuotes = false
    for (const char of line) {
      if (char === '"') {
        inQuotes = !inQuotes
      } else if (char === ',' && !inQuotes) {
        cells.push(current.trim())
        current = ''
      } else {
        current += char
      }
    }
    cells.push(current.trim())
    return cells
  })
}

export function parseDurationString(dur: string): number {
  if (!dur) return 0
  // Handle HH:MM:SS, HH:MM, or decimal hours
  if (dur.includes(':')) {
    const parts = dur.split(':').map(Number)
    if (parts.length === 3) return parts[0] * 3600 + parts[1] * 60 + parts[2]
    if (parts.length === 2) return parts[0] * 3600 + parts[1] * 60
  }
  const hours = parseFloat(dur)
  if (!isNaN(hours)) return Math.round(hours * 3600)
  return 0
}

// Parse locale-variable date strings into YYYY-MM-DD
function parseFlexDate(dateStr: string, formatHint?: DateFormat): string {
  if (!dateStr) return new Date().toISOString().split('T')[0]
  const s = dateStr.trim()

  // YYYY-MM-DD (ISO)
  if (/^\d{4}-\d{1,2}-\d{1,2}$/.test(s)) {
    const [y, m, d] = s.split('-')
    return `${y}-${m.padStart(2, '0')}-${d.padStart(2, '0')}`
  }

  // Slash or dot separated: could be MM/DD/YYYY, DD/MM/YYYY, DD.MM.YYYY
  const match = s.match(/^(\d{1,2})[\/.](\d{1,2})[\/.](\d{2,4})$/)
  if (match) {
    let [, a, b, year] = match
    if (year.length === 2) year = '20' + year
    // If first part > 12, must be day-first (DD/MM/YYYY)
    if (parseInt(a) > 12) return `${year}-${b.padStart(2, '0')}-${a.padStart(2, '0')}`
    // If second part > 12, must be month-first (MM/DD/YYYY)
    if (parseInt(b) > 12) return `${year}-${a.padStart(2, '0')}-${b.padStart(2, '0')}`
    // Use format hint if provided
    if (formatHint === 'DMY') return `${year}-${b.padStart(2, '0')}-${a.padStart(2, '0')}`
    // Default to MDY
    return `${year}-${a.padStart(2, '0')}-${b.padStart(2, '0')}`
  }

  // Last resort: try Date constructor
  const d = new Date(s)
  if (!isNaN(d.getTime())) return d.toISOString().split('T')[0]
  return new Date().toISOString().split('T')[0]
}

// Parse 12h or 24h time strings into HH:MM:SS
function parseFlexTime(timeStr: string): string {
  if (!timeStr) return '00:00:00'
  const s = timeStr.trim()

  // 12-hour: "1:00 PM", "11:30:00 AM"
  const ampm = s.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?\s*(AM|PM)$/i)
  if (ampm) {
    let hour = parseInt(ampm[1])
    const min = ampm[2]
    const sec = ampm[3] || '00'
    const period = ampm[4].toUpperCase()
    if (period === 'PM' && hour !== 12) hour += 12
    if (period === 'AM' && hour === 12) hour = 0
    return `${hour.toString().padStart(2, '0')}:${min}:${sec}`
  }

  // 24-hour: "13:00", "09:30:00"
  const h24 = s.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/)
  if (h24) {
    return `${h24[1].padStart(2, '0')}:${h24[2]}:${h24[3] || '00'}`
  }

  return '00:00:00'
}

function safeDateTime(date: string, time?: string, dateFormat?: DateFormat): string {
  const d = parseFlexDate(date, dateFormat)
  const t = time ? parseFlexTime(time) : '00:00:00'
  return `${d}T${t}`
}

export function findCol(header: string[], ...terms: string[]): number {
  for (const term of terms) {
    const idx = header.findIndex(h => h === term)
    if (idx >= 0) return idx
  }
  for (const term of terms) {
    const idx = header.findIndex(h => h.includes(term))
    if (idx >= 0) return idx
  }
  return -1
}

function col(row: string[], idx: number): string {
  return idx >= 0 ? (row[idx] || '') : ''
}

export function mapTogglCSV(rows: string[][], dateFormat?: DateFormat): ImportEntry[] {
  const header = rows[0].map(h => h.toLowerCase().trim())
  const descIdx = findCol(header, 'description')
  const projIdx = findCol(header, 'project')
  const clientIdx = findCol(header, 'client')
  const taskIdx = findCol(header, 'task')
  const tagIdx = findCol(header, 'tags', 'tag')
  const startDateIdx = findCol(header, 'start date')
  const startTimeIdx = findCol(header, 'start time')
  const durationIdx = findCol(header, 'duration')

  return rows.slice(1).map(row => ({
    project_name: col(row, projIdx) || 'Imported',
    client_name: col(row, clientIdx) || undefined,
    task_name: col(row, taskIdx) || undefined,
    description: col(row, descIdx) || undefined,
    start_time: safeDateTime(col(row, startDateIdx), col(row, startTimeIdx) || undefined, dateFormat),
    duration: parseDurationString(col(row, durationIdx)),
    tags: tagIdx >= 0 && row[tagIdx] ? row[tagIdx].split(',').map(t => t.trim()).filter(Boolean) : undefined,
  }))
}

export function mapClockifyCSV(rows: string[][], dateFormat?: DateFormat): ImportEntry[] {
  const header = rows[0].map(h => h.toLowerCase().trim())
  const descIdx = findCol(header, 'description')
  const projIdx = findCol(header, 'project')
  const clientIdx = findCol(header, 'client')
  const taskIdx = findCol(header, 'task')
  const tagIdx = findCol(header, 'tags', 'tag')
  const startDateIdx = findCol(header, 'start date')
  const startTimeIdx = findCol(header, 'start time')
  // Prefer decimal duration - always a simple number, no format ambiguity
  const durDecIdx = header.findIndex(h => h.includes('duration (decimal)'))
  const durHIdx = header.findIndex(h => h.includes('duration (h)'))
  const durPlainIdx = header.findIndex(h => h === 'duration')

  return rows.slice(1).map(row => {
    let duration = 0
    if (durDecIdx >= 0 && row[durDecIdx]) {
      duration = Math.round(parseFloat(row[durDecIdx]) * 3600)
    } else if (durHIdx >= 0 && row[durHIdx]) {
      duration = parseDurationString(row[durHIdx])
    } else if (durPlainIdx >= 0 && row[durPlainIdx]) {
      duration = parseDurationString(row[durPlainIdx])
    }

    return {
      project_name: col(row, projIdx) || 'Imported',
      client_name: col(row, clientIdx) || undefined,
      task_name: col(row, taskIdx) || undefined,
      description: col(row, descIdx) || undefined,
      start_time: safeDateTime(col(row, startDateIdx), col(row, startTimeIdx) || undefined, dateFormat),
      duration,
      tags: tagIdx >= 0 && row[tagIdx] ? row[tagIdx].split(',').map(t => t.trim()).filter(Boolean) : undefined,
    }
  })
}

export function mapHarvestCSV(rows: string[][], dateFormat?: DateFormat): ImportEntry[] {
  const header = rows[0].map(h => h.toLowerCase().trim())
  const dateIdx = findCol(header, 'date')
  const projIdx = header.findIndex(h => h === 'project')
  const clientIdx = findCol(header, 'client')
  const taskIdx = findCol(header, 'task')
  const notesIdx = findCol(header, 'notes')
  const hoursIdx = header.findIndex(h => h === 'hours')

  return rows.slice(1).map(row => ({
    project_name: col(row, projIdx) || 'Imported',
    client_name: col(row, clientIdx) || undefined,
    task_name: col(row, taskIdx) || undefined,
    description: col(row, notesIdx) || undefined,
    start_time: safeDateTime(col(row, dateIdx), undefined, dateFormat),
    duration: hoursIdx >= 0 && row[hoursIdx] ? Math.round(parseFloat(row[hoursIdx]) * 3600) : 0,
  }))
}

export function mapGenericCSV(rows: string[][], mapping: Record<string, number>): ImportEntry[] {
  return rows.slice(1).map(row => ({
    project_name: row[mapping.project] || 'Imported',
    client_name: mapping.client >= 0 ? row[mapping.client] : undefined,
    task_name: mapping.task >= 0 ? row[mapping.task] : undefined,
    description: mapping.description >= 0 ? row[mapping.description] : undefined,
    start_time: row[mapping.start_time] || new Date().toISOString(),
    duration: mapping.duration >= 0 ? parseDurationString(row[mapping.duration]) : 0,
  }))
}
