import { databases, DATABASE_ID, COLLECTIONS, PROJECT_TICKET_TYPE, Query, ID } from './appwrite'

/**
 * Roadmaps: projektspezifische Plaene als Steckbrett (Spalten-Raster).
 * Ein Dokument pro Knoten; Kanten als sourceIds (Vorgaenger) am Zielknoten.
 * Genau 1 aktiver Plan pro Projekt (Pruefung hier, nicht per Index erzwingbar).
 * Jeder Plan erzeugt automatisch ein Projektticket (Vorbild: createAcquisitionTicket in leads.js).
 */

export const ROADMAP_STATUS = { ACTIVE: 'active', COMPLETED: 'completed' }
export const NODE_STATUS = { OPEN: 'open', IN_PROGRESS: 'in_progress', DONE: 'done' }
export const NODE_KIND = { START: 'start', STEP: 'step', GOAL: 'goal' }

export const NODE_STATUS_LABELS = {
  open: 'Offen',
  in_progress: 'In Arbeit',
  done: 'Fertig',
}

/** Fortschritt in Prozent: fertige Knoten / alle Knoten ausser Start. */
export function computeProgress(nodes) {
  const relevant = (nodes || []).filter((n) => n.kind !== NODE_KIND.START)
  if (!relevant.length) return { percent: 0, done: 0, total: 0 }
  const done = relevant.filter((n) => n.status === NODE_STATUS.DONE).length
  return { percent: Math.round((done / relevant.length) * 100), done, total: relevant.length }
}

export function allGoalsDone(nodes) {
  const goals = (nodes || []).filter((n) => n.kind === NODE_KIND.GOAL)
  return goals.length > 0 && goals.every((n) => n.status === NODE_STATUS.DONE)
}

export function isNodeOverdue(node) {
  if (!node?.deadline || node.status === NODE_STATUS.DONE) return false
  return node.deadline < new Date().toISOString().slice(0, 10)
}

/** Aktiver Plan eines Projekts (oder null). */
export async function fetchActiveRoadmapByProject(projectId) {
  const res = await databases.listDocuments(DATABASE_ID, COLLECTIONS.ROADMAPS, [
    Query.equal('projectId', projectId),
    Query.equal('status', ROADMAP_STATUS.ACTIVE),
    Query.limit(1),
  ])
  return res.documents[0] || null
}

export async function fetchRoadmapByTicketId(ticketId) {
  if (!ticketId) return null
  const res = await databases.listDocuments(DATABASE_ID, COLLECTIONS.ROADMAPS, [
    Query.equal('ticketId', ticketId),
    Query.limit(1),
  ])
  return res.documents[0] || null
}

export async function fetchRoadmapNodes(roadmapId) {
  const res = await databases.listDocuments(DATABASE_ID, COLLECTIONS.ROADMAP_NODES, [
    Query.equal('roadmapId', roadmapId),
    Query.limit(500),
  ])
  return res.documents
}

async function nextWoid() {
  try {
    const res = await databases.listDocuments(DATABASE_ID, COLLECTIONS.WORKORDERS, [
      Query.orderDesc('$createdAt'),
      Query.limit(200),
    ])
    const nums = res.documents.map((d) => parseInt(d.woid)).filter((n) => !isNaN(n) && n > 0)
    return String((nums.length ? Math.max(...nums) : 9999) + 1)
  } catch {
    return String(10000)
  }
}

async function nextWsid() {
  try {
    const res = await databases.listDocuments(DATABASE_ID, COLLECTIONS.WORKSHEETS, [
      Query.orderDesc('wsid'),
      Query.limit(1),
    ])
    const highest = parseInt(res.documents[0]?.wsid)
    return String(isNaN(highest) ? 100000 : highest + 1)
  } catch {
    return String(100000)
  }
}

/** Automatisches Projektticket fuer einen neuen Plan. */
async function createRoadmapTicket(roadmap, project, user) {
  const woid = await nextWoid()
  const data = {
    topic: `Projekt: ${project.projectName}`,
    status: 'Open',
    priority: 2,
    woid,
    type: PROJECT_TICKET_TYPE,
    systemType: 'n/a',
    serviceType: 'Remote',
    assignedTo: user?.$id || '',
    details:
      `Automatisch erstelltes Projektticket fuer die Roadmap "${roadmap.title}" ` +
      `zum Projekt "${project.projectName}".\n\n` +
      `Der Planfortschritt wird hier getrackt: Jede Statusaenderung eines Roadmap-Knotens ` +
      `erzeugt einen Verlaufseintrag (Worksheet). Sind alle Ziel-Knoten fertig, wird das ` +
      `Ticket geschlossen und der Plan archiviert.`,
    createdAt: new Date().toISOString(),
  }
  if (project.customerId) {
    data.customerId = project.customerId
    if (roadmap.customerName) data.customerName = roadmap.customerName
  }
  return databases.createDocument(DATABASE_ID, COLLECTIONS.WORKORDERS, ID.unique(), data)
}

/**
 * Legt einen neuen Plan an: Roadmap-Dokument + Start-Knoten + Ziel-Knoten + Auto-Ticket.
 * Wirft, wenn das Projekt bereits einen aktiven Plan hat.
 */
export async function createRoadmapPlan(project, { title, goalTitle }, user) {
  const existing = await fetchActiveRoadmapByProject(project.$id)
  if (existing) {
    throw new Error(`Das Projekt "${project.projectName}" hat bereits einen aktiven Plan.`)
  }

  let customerName = ''
  if (project.customerId) {
    try {
      const customer = await databases.getDocument(DATABASE_ID, COLLECTIONS.CUSTOMERS, project.customerId)
      customerName = customer.name || ''
    } catch {
      /* Kunde optional */
    }
  }

  const now = new Date().toISOString()
  const columnCount = 3
  const roadmap = await databases.createDocument(DATABASE_ID, COLLECTIONS.ROADMAPS, ID.unique(), {
    projectId: project.$id,
    projectName: project.projectName || '',
    customerId: project.customerId || '',
    customerName,
    title: title || `Plan: ${project.projectName}`,
    status: ROADMAP_STATUS.ACTIVE,
    columnCount,
    createdBy: user?.$id || '',
    createdAt: now,
    updatedAt: now,
  })

  await Promise.all([
    databases.createDocument(DATABASE_ID, COLLECTIONS.ROADMAP_NODES, ID.unique(), {
      roadmapId: roadmap.$id,
      title: 'Start',
      kind: NODE_KIND.START,
      column: 0,
      row: 0,
      status: NODE_STATUS.OPEN,
      createdAt: now,
      updatedAt: now,
    }),
    databases.createDocument(DATABASE_ID, COLLECTIONS.ROADMAP_NODES, ID.unique(), {
      roadmapId: roadmap.$id,
      title: goalTitle || 'Ziel',
      kind: NODE_KIND.GOAL,
      column: columnCount - 1,
      row: 0,
      status: NODE_STATUS.OPEN,
      createdAt: now,
      updatedAt: now,
    }),
  ])

  let ticket = null
  try {
    ticket = await createRoadmapTicket(roadmap, project, user)
    await databases.updateDocument(DATABASE_ID, COLLECTIONS.ROADMAPS, roadmap.$id, {
      ticketId: ticket.$id,
      woid: ticket.woid,
    })
    roadmap.ticketId = ticket.$id
    roadmap.woid = ticket.woid
  } catch {
    /* Ticket ist optional - Plan bleibt bestehen */
  }
  return { roadmap, ticket }
}

/** Verlaufseintrag (Worksheet-Kommentar) am Projektticket, ohne den Ticket-Status zu aendern. */
export async function logRoadmapWorksheet(roadmap, detailsText, user) {
  if (!roadmap?.ticketId) return null
  let ticket
  try {
    ticket = await databases.getDocument(DATABASE_ID, COLLECTIONS.WORKORDERS, roadmap.ticketId)
  } catch {
    return null // Ticket geloescht -> kein Log
  }
  const today = new Date().toISOString().slice(0, 10)
  const wsid = await nextWsid()
  return databases.createDocument(DATABASE_ID, COLLECTIONS.WORKSHEETS, ID.unique(), {
    wsid,
    woid: ticket.woid || roadmap.woid || '',
    workorderId: ticket.$id,
    employeeId: user?.$id || 'system',
    employeeName: user?.name || user?.email || 'System',
    serviceType: 'Remote',
    oldStatus: ticket.status,
    newStatus: ticket.status,
    totalTime: 0,
    startDate: today,
    endDate: today,
    details: detailsText,
    isComment: true,
    createdAt: new Date().toISOString(),
  })
}

/** Knoten-Statuswechsel im Ticketverlauf dokumentieren. */
export async function logNodeStatusWorksheet(roadmap, node, oldStatus, newStatus, user) {
  const from = NODE_STATUS_LABELS[oldStatus] || oldStatus || '-'
  const to = NODE_STATUS_LABELS[newStatus] || newStatus
  return logRoadmapWorksheet(roadmap, `Roadmap-Knoten "${node.title}": ${from} -> ${to}`, user)
}

/**
 * Plan abschliessen: Roadmap archivieren, Ticket schliessen (falls noch offen)
 * und den Abschluss im Verlauf dokumentieren.
 */
export async function completeRoadmap(roadmap, user) {
  const now = new Date().toISOString()
  const updated = await databases.updateDocument(DATABASE_ID, COLLECTIONS.ROADMAPS, roadmap.$id, {
    status: ROADMAP_STATUS.COMPLETED,
    completedAt: now,
    updatedAt: now,
  })
  if (roadmap.ticketId) {
    try {
      const ticket = await databases.getDocument(DATABASE_ID, COLLECTIONS.WORKORDERS, roadmap.ticketId)
      if (ticket.status !== 'Closed') {
        const wsid = await nextWsid()
        const today = now.slice(0, 10)
        await databases.createDocument(DATABASE_ID, COLLECTIONS.WORKSHEETS, ID.unique(), {
          wsid,
          woid: ticket.woid || '',
          workorderId: ticket.$id,
          employeeId: user?.$id || 'system',
          employeeName: user?.name || user?.email || 'System',
          serviceType: 'Remote',
          oldStatus: ticket.status,
          newStatus: 'Closed',
          totalTime: 0,
          startDate: today,
          endDate: today,
          details: `Roadmap "${roadmap.title}" abgeschlossen: alle Ziel-Knoten fertig. Ticket automatisch geschlossen.`,
          isComment: true,
          createdAt: now,
        })
        await databases.updateDocument(DATABASE_ID, COLLECTIONS.WORKORDERS, ticket.$id, { status: 'Closed' })
      } else {
        await logRoadmapWorksheet({ ...roadmap, status: ROADMAP_STATUS.COMPLETED }, `Roadmap "${roadmap.title}" abgeschlossen (Ticket war bereits geschlossen).`, user)
      }
    } catch {
      /* Ticket fehlt -> nur archivieren */
    }
  }
  return updated
}

/**
 * Aktiven Plan loeschen (destruktiv): alle Knoten + Roadmap entfernen,
 * Auto-Ticket auf Cancelled setzen. Abgeschlossene Plaene werden nie geloescht.
 */
export async function deleteRoadmapPlan(roadmap, user) {
  const nodes = await fetchRoadmapNodes(roadmap.$id)
  await logRoadmapWorksheet(roadmap, `Roadmap "${roadmap.title}" geloescht. Ticket wird abgebrochen.`, user)
  for (const node of nodes) {
    await databases.deleteDocument(DATABASE_ID, COLLECTIONS.ROADMAP_NODES, node.$id)
  }
  await databases.deleteDocument(DATABASE_ID, COLLECTIONS.ROADMAPS, roadmap.$id)
  if (roadmap.ticketId) {
    try {
      const ticket = await databases.getDocument(DATABASE_ID, COLLECTIONS.WORKORDERS, roadmap.ticketId)
      if (ticket.status !== 'Closed' && ticket.status !== 'Cancelled') {
        await databases.updateDocument(DATABASE_ID, COLLECTIONS.WORKORDERS, ticket.$id, { status: 'Cancelled' })
      }
    } catch {
      /* Ticket fehlt -> nichts zu tun */
    }
  }
}
