import { ClubRequest, ClubRequestNote } from '../models/index.js';
import { getSafeErrorMessage } from '../utils/errorUtils.js';

const TERMINAL_REQUEST_STATUSES = new Set(['converted', 'rejected', 'archived']);

function isMissingRequestTableError(error) {
  return error?.original?.code === 'ER_NO_SUCH_TABLE'
    && /club_requests|club_request_notes/.test(String(error?.original?.sqlMessage || ''));
}

function normalizeRequestPayload(payload = {}) {
  return {
    requestType: payload.requestType || 'contact',
    subject: payload.subject?.trim() || null,
    firstName: payload.firstName?.trim() || null,
    lastName: payload.lastName?.trim() || null,
    email: payload.email?.trim() || null,
    phone: payload.phone?.trim() || null,
    message: payload.message?.trim() || null,
  };
}

async function loadRequestOrThrow(clubId, requestId) {
  const request = await ClubRequest.findOne({
    where: {
      id: requestId,
      clubId,
    },
    include: [
      {
        model: ClubRequestNote,
        as: 'notes',
        required: false,
      },
    ],
    order: [[{ model: ClubRequestNote, as: 'notes' }, 'createdAt', 'DESC']],
  });

  if (!request) {
    const error = new Error('Anfrage wurde nicht gefunden.');
    error.statusCode = 404;
    throw error;
  }

  return request;
}

export const listClubRequests = async (req, res) => {
  try {
    const { clubId } = req.params;
    let requests = [];
    try {
      requests = await ClubRequest.findAll({
        where: { clubId },
        include: [
          {
            model: ClubRequestNote,
            as: 'notes',
            required: false,
          },
        ],
        order: [
          ['receivedAt', 'DESC'],
          [{ model: ClubRequestNote, as: 'notes' }, 'createdAt', 'DESC'],
        ],
      });
    } catch (error) {
      if (!isMissingRequestTableError(error)) {
        throw error;
      }
    }

    res.status(200).json({ requests });
  } catch (error) {
    console.error('[listClubRequests] - Error:', error);
    res.status(error.statusCode || 500).json({
      error: getSafeErrorMessage(error, 'Anfragen konnten nicht geladen werden.'),
    });
  }
};

export const createClubRequest = async (req, res) => {
  try {
    const { clubId } = req.params;
    const payload = normalizeRequestPayload(req.body);

    if (!payload.subject && !payload.message) {
      return res.status(400).json({ error: 'Betreff oder Nachricht sind erforderlich.' });
    }

    const request = await ClubRequest.create({
      clubId,
      ...payload,
      receivedAt: new Date(),
    });

    const created = await loadRequestOrThrow(clubId, request.id);
    res.status(201).json({ request: created });
  } catch (error) {
    console.error('[createClubRequest] - Error:', error);
    res.status(error.statusCode || 500).json({
      error: getSafeErrorMessage(error, 'Anfrage konnte nicht gespeichert werden.'),
    });
  }
};

export const updateClubRequest = async (req, res) => {
  try {
    const { clubId, requestId } = req.params;
    const request = await loadRequestOrThrow(clubId, requestId);
    const payload = normalizeRequestPayload(req.body);

    await request.update(payload);
    const updated = await loadRequestOrThrow(clubId, requestId);
    res.status(200).json({ request: updated });
  } catch (error) {
    console.error('[updateClubRequest] - Error:', error);
    res.status(error.statusCode || 500).json({
      error: getSafeErrorMessage(error, 'Anfrage konnte nicht gespeichert werden.'),
    });
  }
};

export const updateClubRequestStatus = async (req, res) => {
  try {
    const { clubId, requestId } = req.params;
    const { status } = req.body || {};

    if (!status) {
      return res.status(400).json({ error: 'Status fehlt.' });
    }

    const request = await loadRequestOrThrow(clubId, requestId);
    await request.update({
      status,
      closedAt: TERMINAL_REQUEST_STATUSES.has(status) ? new Date() : null,
    });

    const updated = await loadRequestOrThrow(clubId, requestId);
    res.status(200).json({ request: updated });
  } catch (error) {
    console.error('[updateClubRequestStatus] - Error:', error);
    res.status(error.statusCode || 500).json({
      error: getSafeErrorMessage(error, 'Status konnte nicht gespeichert werden.'),
    });
  }
};

export const addClubRequestNote = async (req, res) => {
  try {
    const { clubId, requestId } = req.params;
    const body = String(req.body?.body || '').trim();

    if (!body) {
      return res.status(400).json({ error: 'Notiztext fehlt.' });
    }

    await loadRequestOrThrow(clubId, requestId);

    await ClubRequestNote.create({
      clubRequestId: requestId,
      createdByUserId: req.user?.id || null,
      body,
    });

    const updated = await loadRequestOrThrow(clubId, requestId);
    res.status(201).json({ request: updated });
  } catch (error) {
    console.error('[addClubRequestNote] - Error:', error);
    res.status(error.statusCode || 500).json({
      error: getSafeErrorMessage(error, 'Notiz konnte nicht gespeichert werden.'),
    });
  }
};
