/** FEEDBACK: API client for the "Fehler melden" report sink (POST /feedback). */
import { api, API_BASE_URL } from './client'

const RESOURCE = '/feedback'

/** Metadaten eines Ticket-Anhangs (Bytes separat über attachmentUrl). */
export interface FeedbackAttachment {
  id: string
  fileName: string
  contentType: string
  size: number
}

/** Which view a report was filed from (matches the backend Context contract). */
export type FeedbackContext = 'stammbaum' | 'gerbil-detail' | 'litter-detail' | 'contact-detail'

/** Payload for POST /feedback. Debug fields are captured automatically by the caller. */
export interface FeedbackInput {
  message: string
  context: FeedbackContext
  gerbilId?: string | null
  litterId?: string | null
  contactId?: string | null
  entityName?: string | null
  url?: string | null
  clientTimestamp?: string | null
}

/**
 * Ticket lifecycle status (matches the backend Status contract).
 *  - Open       — neu, noch keine Rückfrage.
 *  - NeedsInfo  — eine Rückfrage wurde gestellt, wartet auf die Antwort der Züchterin.
 *  - Answered   — die Züchterin hat geantwortet.
 *  - Resolved   — erledigt.
 */
export type FeedbackStatus = 'Open' | 'NeedsInfo' | 'Answered' | 'Resolved'

/** Eine vergangene Frage/Antwort-Runde im Verlauf (Thread) eines Tickets. */
export interface FeedbackThreadEntry {
  /** „maintainer" = Rückfrage, „breeder" = Antwort der Züchterin. */
  role: 'maintainer' | 'breeder'
  text: string
  /** Zeitpunkt der Runde (ISO-8601) oder null. */
  at: string | null
}

export interface Feedback {
  id: string
  message: string
  context: string
  gerbilId: string | null
  litterId: string | null
  contactId: string | null
  entityName: string | null
  url: string | null
  clientTimestamp: string | null
  userAgent: string | null
  createdAt: string
  status: FeedbackStatus
  resolvedAt: string | null
  /**
   * Zeitpunkt des Wiederöffnens — gesetzt, wenn ein ECHT gelöstes Ticket (ohne offene
   * Rückfrage) wieder geöffnet wurde; null sonst. Wird als „Wieder geöffnet am" angezeigt.
   */
  reopenedAt: string | null
  /**
   * Soft-Delete-Marker: gesetzt, wenn das Ticket über die UI gelöscht wurde (wiederherstellbar).
   * Solche Tickets erscheinen nur in der „Gelöscht"-Kategorie. null = nicht gelöscht.
   */
  deletedAt: string | null
  /** Optionale Kategorie/Thema (von der KI gesetzt), z. B. „Genetik", „Import". null = ohne. */
  category: string | null
  /** War die Lösung hilfreich? true=👍, false=👎, null=keine Rückmeldung. */
  helpful: boolean | null
  /** Angehängte Dateien/Fotos (nur Metadaten; Bytes über attachmentUrl laden). */
  attachments: FeedbackAttachment[]
  /** Rückfrage einer/eines Betreuenden an die Züchterin (falls vorhanden). */
  question: string | null
  /** Antwort der Züchterin auf die Rückfrage (falls vorhanden). */
  answer: string | null
  /** Zeitpunkt der Antwort der Züchterin. */
  answeredAt: string | null
  /** Laienverständlicher Changelog, der beim Schließen geschrieben wird (sichtbar). */
  fixNote: string | null
  /**
   * INTERN: Arbeitsgedächtnis des Agenten — wird vom Backend geliefert, darf aber
   * NIEMALS in der Züchterin-UI angezeigt werden.
   */
  agentContext: string | null
  /** Frühere Frage/Antwort-Runden (älteste zuerst); die aktuelle offene Runde bleibt in question/answer. */
  thread: FeedbackThreadEntry[]
}

/** Alias used by the "Meine Tickets" area for readability. */
export type FeedbackTicket = Feedback

/**
 * Payload for PUT /feedback/{id}: edit the message, toggle the status, attach a
 * clarifying question (Rückfrage) or submit the breeder's answer.
 */
export interface FeedbackUpdate {
  message?: string
  status?: FeedbackStatus
  /** Rückfrage anhängen (nicht leer ⇒ Status wird serverseitig auf NeedsInfo gesetzt). */
  question?: string
  /** Antwort der Züchterin (nicht leer ⇒ Status Answered + answeredAt). */
  answer?: string
  /** Laienverständlicher Changelog (typisch zusammen mit status: "Resolved" gesetzt). */
  fixNote?: string
  /** INTERN: Arbeitsgedächtnis des Agenten (ändert den Status nicht). */
  agentContext?: string
  /** Kategorie/Thema setzen (leer ⇒ löschen). */
  category?: string
  /** 👍/👎-Rückmeldung auf ein gelöstes Ticket. */
  helpful?: boolean
}

export function submitFeedback(body: FeedbackInput): Promise<Feedback> {
  return api.post<Feedback>(RESOURCE, body)
}

/** List all feedback tickets, newest first. */
export function listFeedback(): Promise<Feedback[]> {
  return api.get<Feedback[]>(RESOURCE)
}

/** Edit a ticket's message and/or status. */
export function updateFeedback(id: string, body: FeedbackUpdate): Promise<Feedback> {
  return api.put<Feedback>(`${RESOURCE}/${id}`, body)
}

/** Convenience: submit the breeder's answer to a ticket's clarifying question. */
export function answerTicket(id: string, answer: string): Promise<Feedback> {
  return updateFeedback(id, { answer })
}

/** Soft-delete a ticket (moves it into the "Gelöscht" category; recoverable via restore). */
export function deleteFeedback(id: string): Promise<void> {
  return api.delete(`${RESOURCE}/${id}`)
}

/** Restore a soft-deleted ticket (DeletedAt → null); it returns to its prior status. */
export function restoreFeedback(id: string): Promise<Feedback> {
  return api.post<Feedback>(`${RESOURCE}/${id}/restore`, {})
}

/** Volle URL zu den Bytes eines Anhangs (für <img src> / Download). */
export function attachmentUrl(attachmentId: string): string {
  return `${API_BASE_URL}${RESOURCE}/attachments/${attachmentId}`
}

/** Einen Anhang (base64) an ein Ticket hochladen. */
export function uploadAttachment(
  feedbackId: string,
  body: { fileName: string; contentType: string; dataBase64: string },
): Promise<FeedbackAttachment> {
  return api.post<FeedbackAttachment>(`${RESOURCE}/${feedbackId}/attachments`, body)
}

/** Einen Anhang löschen. */
export function deleteAttachment(attachmentId: string): Promise<void> {
  return api.delete(`${RESOURCE}/attachments/${attachmentId}`)
}

/** Eine Browser-Datei als Upload-Payload (base64) einlesen. */
export function readFileAsUpload(
  file: File,
): Promise<{ fileName: string; contentType: string; dataBase64: string }> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = () => {
      const result = String(reader.result)
      const comma = result.indexOf(',')
      resolve({
        fileName: file.name,
        contentType: file.type || 'application/octet-stream',
        dataBase64: comma >= 0 ? result.slice(comma + 1) : result,
      })
    }
    reader.onerror = () => reject(reader.error)
    reader.readAsDataURL(file)
  })
}
