import { addOrUpdateSchedule } from '../../services/meilisearch/index.js';
import { uploadConcertPoster, uploadConcertMerchandise } from '../../services/image.js';
import { CATEGORY_IDS } from '../../config/index.js';
import { withTransaction } from '../../utils/transaction.js';
import { badRequest, serverError } from '../../utils/error.js';

const CONCERT_CATEGORY_ID = CATEGORY_IDS.CONCERT;

/**
 * 콘서트 관련 관리자 라우트
 */
export default async function concertRoutes(fastify) {
  const { db, meilisearch } = fastify;

  /**
   * POST /api/admin/concert/schedule
   * 콘서트 일정 저장 (multipart/form-data)
   */
  fastify.post('/schedule', {
    preHandler: [fastify.authenticate],
  }, async (request, reply) => {
    const parts = request.parts();

    // multipart 파싱
    let title = '';
    let memberIds = [];
    let rounds = [];
    let setlist = [];
    let posterBuffer = null;
    const merchandiseBuffers = [];

    for await (const part of parts) {
      if (part.type === 'file') {
        const buffer = await part.toBuffer();
        if (part.fieldname === 'poster') {
          posterBuffer = buffer;
        } else if (part.fieldname === 'merchandise') {
          merchandiseBuffers.push(buffer);
        }
      } else {
        // field
        if (part.fieldname === 'title') title = part.value;
        else if (part.fieldname === 'memberIds') memberIds = JSON.parse(part.value);
        else if (part.fieldname === 'rounds') rounds = JSON.parse(part.value);
        else if (part.fieldname === 'setlist') setlist = JSON.parse(part.value);
      }
    }

    // 검증
    if (!title || !title.trim()) {
      return badRequest(reply, '공연명은 필수입니다.');
    }
    if (!rounds || rounds.length === 0) {
      return badRequest(reply, '최소 1개 이상의 공연 일정이 필요합니다.');
    }
    for (const round of rounds) {
      if (!round.date) {
        return badRequest(reply, '모든 회차에 날짜는 필수입니다.');
      }
    }

    try {
      // 트랜잭션으로 DB 작업 수행
      const result = await withTransaction(db, async (conn) => {
        // 1. concert_series 생성
        const [seriesResult] = await conn.query(
          'INSERT INTO concert_series (title) VALUES (?)',
          [title.trim()]
        );
        const seriesId = seriesResult.insertId;

        // 2. 포스터 업로드 → images → concert_series.poster_id
        if (posterBuffer) {
          const { originalUrl, mediumUrl, thumbUrl } = await uploadConcertPoster(seriesId, posterBuffer);
          const [imageResult] = await conn.query(
            'INSERT INTO images (original_url, medium_url, thumb_url) VALUES (?, ?, ?)',
            [originalUrl, mediumUrl, thumbUrl]
          );
          await conn.query(
            'UPDATE concert_series SET poster_id = ? WHERE id = ?',
            [imageResult.insertId, seriesId]
          );
        }

        // 3. 각 회차 처리
        const scheduleIds = [];
        const concertIds = [];

        for (const round of rounds) {
          // venue 처리
          let venueId = null;
          if (round.venueId) {
            venueId = round.venueId;
          } else if (round.venueName) {
            const [venueResult] = await conn.query(
              'INSERT INTO concert_venues (name, country, address, lat, lng) VALUES (?, ?, ?, ?, ?)',
              [round.venueName, round.venueCountry || null, round.venueAddress || null, round.venueLat || null, round.venueLng || null]
            );
            venueId = venueResult.insertId;
          }

          // schedules 테이블
          const [scheduleResult] = await conn.query(
            'INSERT INTO schedules (category_id, title, date, time) VALUES (?, ?, ?, ?)',
            [CONCERT_CATEGORY_ID, title.trim(), round.date, round.time || null]
          );
          const scheduleId = scheduleResult.insertId;
          scheduleIds.push(scheduleId);

          // schedule_concert 테이블
          const [concertResult] = await conn.query(
            'INSERT INTO schedule_concert (schedule_id, series_id, venue_id) VALUES (?, ?, ?)',
            [scheduleId, seriesId, venueId]
          );
          concertIds.push(concertResult.insertId);

          // schedule_members 테이블
          if (memberIds.length > 0) {
            const values = memberIds.map(memberId => [scheduleId, memberId]);
            await conn.query(
              'INSERT INTO schedule_members (schedule_id, member_id) VALUES ?',
              [values]
            );
          }
        }

        // 4. 세트리스트 (첫 번째 concert_id 기준으로 저장)
        const primaryConcertId = concertIds[0];

        for (let i = 0; i < setlist.length; i++) {
          const song = setlist[i];
          if (!song.songName || !song.songName.trim()) continue;

          const [setlistResult] = await conn.query(
            'INSERT INTO concert_setlists (concert_id, order_num, song_name, album_name) VALUES (?, ?, ?, ?)',
            [primaryConcertId, i + 1, song.songName.trim(), song.albumName?.trim() || null]
          );
          const setlistId = setlistResult.insertId;

          // 곡별 멤버
          if (song.memberIds && song.memberIds.length > 0) {
            const memberValues = song.memberIds.map(memberId => [setlistId, memberId]);
            await conn.query(
              'INSERT INTO concert_setlist_members (setlist_id, member_id) VALUES ?',
              [memberValues]
            );
          }
        }

        // 5. 굿즈(MD) 이미지
        for (let i = 0; i < merchandiseBuffers.length; i++) {
          const filename = `${String(i + 1).padStart(2, '0')}.webp`;
          const { originalUrl, mediumUrl, thumbUrl } = await uploadConcertMerchandise(seriesId, filename, merchandiseBuffers[i]);

          const [imageResult] = await conn.query(
            'INSERT INTO images (original_url, medium_url, thumb_url) VALUES (?, ?, ?)',
            [originalUrl, mediumUrl, thumbUrl]
          );
          await conn.query(
            'INSERT INTO concert_series_md (series_id, image_id, sort_order) VALUES (?, ?, ?)',
            [seriesId, imageResult.insertId, i + 1]
          );
        }

        return { seriesId, scheduleIds };
      });

      // 6. Meilisearch 동기화 (트랜잭션 외부)
      const [categoryRows] = await db.query(
        'SELECT name, color FROM schedule_categories WHERE id = ?',
        [CONCERT_CATEGORY_ID]
      );
      const category = categoryRows[0] || {};

      let memberNames = '';
      if (memberIds.length > 0) {
        const [members] = await db.query(
          'SELECT name FROM members WHERE id IN (?) ORDER BY id',
          [memberIds]
        );
        memberNames = members.map(m => m.name).join(',');
      }

      for (const scheduleId of result.scheduleIds) {
        const [scheduleRows] = await db.query(
          'SELECT title, date, time FROM schedules WHERE id = ?',
          [scheduleId]
        );
        const s = scheduleRows[0];
        if (s) {
          await addOrUpdateSchedule(meilisearch, {
            id: scheduleId,
            title: s.title,
            date: s.date instanceof Date ? s.date.toISOString().split('T')[0] : s.date,
            time: s.time || '',
            category_id: CONCERT_CATEGORY_ID,
            category_name: category.name || '',
            category_color: category.color || '',
            member_names: memberNames,
          });
        }
      }

      return { success: true, seriesId: result.seriesId };
    } catch (err) {
      fastify.log.error(`콘서트 일정 저장 오류: ${err.message}`);
      return serverError(reply, err.message);
    }
  });
}
