import API_CONFIG from '../config/api';
import apiService from './apiService';
import { formatFrappeApiError } from '../utils/frappeErrorMessage';

export const WO_FEEDBACK_WEB_FORM = 'wo-feedback';
export const WO_FEEDBACK_DOCTYPE = 'WO Feedback';

export interface WoFeedbackRecord {
  name: string;
  work_order: string;
  requester_name?: string;
  rating?: string;
  comments?: string;
}

export interface WoFeedbackWebFormConfig {
  title: string;
  introductionHtml: string;
  introductionText: string;
  buttonLabel: string;
  successTitle: string;
  successMessage: string;
  ratingOptions: string[];
}

export interface WoFeedbackSubmitPayload {
  work_order: string;
  requester_name: string;
  rating: string;
  comments?: string;
}

async function getCsrfToken(): Promise<string | null> {
  const authed = await apiService.getCSRFToken();
  if (authed) return authed;
  return apiService.getCSRFTokenForGuest();
}

async function callMethod<T>(method: string, args: Record<string, unknown> = {}): Promise<T> {
  const csrf = await getCsrfToken();
  const headers: Record<string, string> = {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  };
  if (csrf) headers['X-Frappe-CSRF-Token'] = csrf;

  const res = await fetch(`${API_CONFIG.BASE_URL}/api/method/${method}`, {
    method: 'POST',
    credentials: 'include',
    headers,
    body: JSON.stringify(args),
  });

  const body = await res.json().catch(() => ({}));
  if (!res.ok || body.exc) {
    throw new Error(formatFrappeApiError(body) || body?.message || `HTTP ${res.status}`);
  }
  // Frappe omits `message` when the Python method returns None — response is `{}`.
  if (!Object.prototype.hasOwnProperty.call(body, 'message')) {
    return null as T;
  }
  return body.message as T;
}

function parseSelectOptions(options?: string): string[] {
  if (!options) return [];
  return options
    .split('\n')
    .map(o => o.trim())
    .filter(Boolean);
}

function stripIntroductionHtml(html?: string): string {
  if (!html) return '';
  if (typeof document === 'undefined') {
    return html.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
  }
  const doc = new DOMParser().parseFromString(html, 'text/html');
  return (doc.body.textContent || '').replace(/\s+/g, ' ').trim();
}

export function parseWebFormConfig(raw: { web_form?: Record<string, unknown> }): WoFeedbackWebFormConfig {
  const wf = raw?.web_form || {};
  const fields = (wf.web_form_fields as Array<{ fieldname?: string; options?: string }>) || [];
  const ratingField = fields.find(f => f.fieldname === 'rating');

  return {
    title: String(wf.title || 'WO Feedback'),
    introductionHtml: String(wf.introduction_text || ''),
    introductionText: stripIntroductionHtml(String(wf.introduction_text || '')),
    buttonLabel: String(wf.button_label || 'Save'),
    successTitle: String(wf.success_title || 'Feedback Submitted'),
    successMessage: String(wf.success_message || 'Your feedback was submitted successfully.'),
    ratingOptions: parseSelectOptions(ratingField?.options),
  };
}

export async function getWebFormConfig(): Promise<WoFeedbackWebFormConfig> {
  const params = new URLSearchParams({
    doctype: WO_FEEDBACK_DOCTYPE,
    web_form_name: WO_FEEDBACK_WEB_FORM,
  });

  const res = await fetch(
    `${API_CONFIG.BASE_URL}/api/method/frappe.website.doctype.web_form.web_form.get_form_data?${params}`,
    { credentials: 'include', headers: { Accept: 'application/json' } },
  );
  const body = await res.json().catch(() => ({}));
  if (!res.ok || body.exc) {
    throw new Error(formatFrappeApiError(body) || 'Failed to load web form');
  }
  return parseWebFormConfig(body.message || body);
}

export async function getFeedbackForWorkOrder(workOrder: string): Promise<WoFeedbackRecord | null> {
  const result = await callMethod<WoFeedbackRecord | null>(
    'asset_lite.api.wo_feedback_api.get_wo_feedback_for_work_order',
    { work_order: workOrder },
  );
  if (!result?.name) return null;
  return result;
}

export async function submitFeedback(payload: WoFeedbackSubmitPayload): Promise<WoFeedbackRecord> {
  const data = JSON.stringify({
    work_order: payload.work_order,
    requester_name: payload.requester_name,
    rating: payload.rating,
    comments: payload.comments || '',
    doctype: WO_FEEDBACK_DOCTYPE,
  });

  return callMethod<WoFeedbackRecord>(
    'frappe.website.doctype.web_form.web_form.accept',
    { web_form: WO_FEEDBACK_WEB_FORM, data },
  );
}

const woFeedbackWebFormService = {
  getWebFormConfig,
  getFeedbackForWorkOrder,
  submitFeedback,
  parseWebFormConfig,
};

export default woFeedbackWebFormService;
