import { sql } from '../../../lib/sql.js';
import { getUserFromRequest } from '../../../lib/permission-middleware';
import { pickDesignFields } from '../../../lib/custom-cards-fields.js';
import { isExistingGame } from '../../../lib/designer-games.js';

const CUSTOM_GAME = 'Custom';
const CUSTOM_SET = 'Designs';

export default async function handler(req, res) {
  try {
    const user = await getUserFromRequest(req);
    if (!user) {
      return res.status(401).json({ error: 'Authentication required' });
    }

    if (req.method === 'GET') {
      const result = await sql`
        SELECT c.id, c.card_id, c.name, c.mana_cost, c.card_type, c.rarity,
               c.rules_text, c.actions, c.flavor_quote, c.power, c.toughness,
               c.frame_id, c.artwork_url, c.art_mode,
               c.game_target, c.custom_game_id, g.name AS custom_game_name,
               f.id AS frame_pk, f.name AS frame_name, f.palette AS frame_palette,
               f.texture_url AS frame_texture,
               f.frame_image_url AS frame_image,
               f.layout AS frame_layout,
               c.created_at, c.updated_at
        FROM custom_cards c
        LEFT JOIN custom_games g ON g.id = c.custom_game_id
        LEFT JOIN custom_frames f ON f.id = c.custom_frame_id
        WHERE c.user_id = ${user.userId}
        ORDER BY c.updated_at DESC
      `;
      const designs = result.rows.map((row) => ({
        ...row,
        custom_frame:
          row.frame_pk != null
            ? {
                id: row.frame_pk,
                name: row.frame_name,
                palette: row.frame_palette,
                texture_url: row.frame_texture,
                frame_image_url: row.frame_image,
                layout: row.frame_layout,
              }
            : null,
      }));
      return res.status(200).json({
        designs: designs.map(
          ({ frame_pk, frame_name, frame_palette, frame_texture, frame_image, frame_layout, ...rest }) => rest
        ),
      });
    }

    if (req.method === 'POST') {
      const design = await createDesign(user.userId, req.body);
      if (!design) {
        return res.status(400).json({ error: 'Name is required' });
      }
      return res.status(201).json({ design });
    }

    return res.status(405).json({ error: 'Method not allowed' });
  } catch (error) {
    console.error('Custom cards API error:', error);
    return res.status(500).json({ error: 'Internal server error' });
  }
}

async function createDesign(userId, body) {
  const f = pickDesignFields(body);
  if (!f.name) return null;

  const catalogGame = await resolveCatalogGame(userId, f);

  const inserted = await sql`
    INSERT INTO custom_cards
      (user_id, name, mana_cost, card_type, rarity, rules_text,
       actions, flavor_quote, power, toughness, frame_id, artwork_url,
       art_mode, game_target, custom_game_id, custom_frame_id)
    VALUES
      (${userId}, ${f.name}, ${f.manaCost}, ${f.cardType}, ${f.rarity},
       ${f.rulesText}, ${f.actions}, ${f.flavorQuote}, ${f.power},
       ${f.toughness}, ${f.frameId}, ${f.artworkUrl}, ${f.artMode},
       ${f.gameTarget}, ${f.customGameId}, ${f.customFrameId})
    RETURNING *
  `;
  const design = inserted.rows[0];

  // Mirror into the shared catalog so the design shows up in My Cards,
  // lists, and decks through the normal card joins.
  const cardId = await syncCatalogCard(design, f, catalogGame);
  if (cardId) {
    await ensureOwnedRow(userId, cardId);
    const linked = await sql`
      UPDATE custom_cards SET card_id = ${cardId} WHERE id = ${design.id}
      RETURNING *
    `;
    return linked.rows[0];
  }
  return design;
}

/**
 * Resolve the catalog `game` value for a design: an existing system code,
 * the owning custom game's name, or the generic 'Custom' bucket.
 */
export async function resolveCatalogGame(userId, fields) {
  if (fields.gameTarget && isExistingGame(fields.gameTarget)) {
    return fields.gameTarget;
  }
  if (fields.customGameId) {
    const rows = await sql`
      SELECT name FROM custom_games
      WHERE id = ${fields.customGameId} AND user_id = ${userId}
    `;
    if (rows.rows.length > 0) {
      // cards.game is VARCHAR(50) — custom game names cap at 100, so clip.
      return rows.rows[0].name.slice(0, 50);
    }
  }
  return CUSTOM_GAME;
}

/** Create/update the catalog twin of a custom design; returns card id. */
export async function syncCatalogCard(design, fields, catalogGame) {
  const values = {
    name: fields.name,
    setName: CUSTOM_SET,
    setCode: 'DSGN',
    rarity: fields.rarity,
    game: catalogGame || CUSTOM_GAME,
    manaCost: fields.manaCost,
    cardType: fields.cardType,
    oracleText:
      [fields.actions, fields.rulesText, fields.flavorQuote]
        .filter(Boolean)
        .join('\n\n') || null,
    imageUrl: fields.artworkUrl,
  };

  if (design.card_id) {
    const updated = await sql`
      UPDATE cards SET
        name = ${values.name}, set_name = ${values.setName},
        set_code = ${values.setCode}, rarity = ${values.rarity},
        mana_cost = ${values.manaCost}, card_type = ${values.cardType},
        oracle_text = ${values.oracleText}, image_url = ${values.imageUrl},
        updated_at = CURRENT_TIMESTAMP
      WHERE id = ${design.card_id}
      RETURNING id
    `;
    if (updated.rows.length > 0) return updated.rows[0].id;
  }

  const inserted = await sql`
    INSERT INTO cards (name, set_name, set_code, rarity, game,
                       mana_cost, card_type, oracle_text, image_url)
    VALUES (${values.name}, ${values.setName}, ${values.setCode},
            ${values.rarity}, ${values.game}, ${values.manaCost},
            ${values.cardType}, ${values.oracleText}, ${values.imageUrl})
    RETURNING id
  `;
  return inserted.rows[0].id;
}

/** Idempotently give the designer one copy of their own creation. */
export async function ensureOwnedRow(userId, cardId) {
  await sql`
    INSERT INTO user_cards (user_id, card_id, quantity)
    VALUES (${userId}, ${cardId}, 1)
    ON CONFLICT (user_id, card_id, is_foil)
    DO NOTHING
  `;
}
