import {
  uploadAlbumCover,
  deleteAlbumCover,
} from '../../services/image.js';
import photosRoutes from './photos.js';
import teasersRoutes from './teasers.js';

/**
 * 앨범 라우트
 * GET: 공개, POST/PUT/DELETE: 인증 필요
 */
export default async function albumsRoutes(fastify) {
  const { db } = fastify;

  // 하위 라우트 등록
  fastify.register(photosRoutes);
  fastify.register(teasersRoutes);

  /**
   * 앨범 상세 정보 조회 헬퍼 함수 (트랙, 티저, 컨셉포토 포함)
   */
  async function getAlbumDetails(album) {
    const [tracks] = await db.query(
      'SELECT * FROM album_tracks WHERE album_id = ? ORDER BY track_number',
      [album.id]
    );
    album.tracks = tracks;

    const [teasers] = await db.query(
      `SELECT original_url, medium_url, thumb_url, video_url, media_type
       FROM album_teasers WHERE album_id = ? ORDER BY sort_order`,
      [album.id]
    );
    album.teasers = teasers;

    const [photos] = await db.query(
      `SELECT
        p.id, p.original_url, p.medium_url, p.thumb_url, p.photo_type, p.concept_name, p.sort_order,
        p.width, p.height,
        GROUP_CONCAT(m.name ORDER BY m.id SEPARATOR ', ') as members
      FROM album_photos p
      LEFT JOIN album_photo_members pm ON p.id = pm.photo_id
      LEFT JOIN members m ON pm.member_id = m.id
      WHERE p.album_id = ?
      GROUP BY p.id
      ORDER BY p.sort_order`,
      [album.id]
    );

    const conceptPhotos = {};
    for (const photo of photos) {
      const concept = photo.concept_name || 'Default';
      if (!conceptPhotos[concept]) {
        conceptPhotos[concept] = [];
      }
      conceptPhotos[concept].push({
        id: photo.id,
        original_url: photo.original_url,
        medium_url: photo.medium_url,
        thumb_url: photo.thumb_url,
        width: photo.width,
        height: photo.height,
        type: photo.photo_type,
        members: photo.members,
        sortOrder: photo.sort_order,
      });
    }
    album.conceptPhotos = conceptPhotos;

    return album;
  }

  // ==================== GET (공개) ====================

  /**
   * GET /api/albums
   */
  fastify.get('/', {
    schema: {
      tags: ['albums'],
      summary: '전체 앨범 목록 조회',
    },
  }, async () => {
    const [albums] = await db.query(`
      SELECT id, title, folder_name, album_type, album_type_short, release_date,
             cover_original_url, cover_medium_url, cover_thumb_url, description
      FROM albums
      ORDER BY release_date DESC
    `);

    for (const album of albums) {
      const [tracks] = await db.query(
        `SELECT id, track_number, title, is_title_track, duration, lyricist, composer, arranger
         FROM album_tracks WHERE album_id = ? ORDER BY track_number`,
        [album.id]
      );
      album.tracks = tracks;
    }

    return albums;
  });

  /**
   * GET /api/albums/by-name/:albumName/track/:trackTitle
   */
  fastify.get('/by-name/:albumName/track/:trackTitle', {
    schema: {
      tags: ['albums'],
      summary: '앨범명과 트랙명으로 트랙 조회',
    },
  }, async (request, reply) => {
    const albumName = decodeURIComponent(request.params.albumName);
    const trackTitle = decodeURIComponent(request.params.trackTitle);

    const [albums] = await db.query(
      'SELECT * FROM albums WHERE folder_name = ? OR title = ?',
      [albumName, albumName]
    );

    if (albums.length === 0) {
      return reply.code(404).send({ error: '앨범을 찾을 수 없습니다.' });
    }

    const album = albums[0];

    const [tracks] = await db.query(
      'SELECT * FROM album_tracks WHERE album_id = ? AND title = ?',
      [album.id, trackTitle]
    );

    if (tracks.length === 0) {
      return reply.code(404).send({ error: '트랙을 찾을 수 없습니다.' });
    }

    const track = tracks[0];

    const [otherTracks] = await db.query(
      'SELECT id, track_number, title, is_title_track, duration FROM album_tracks WHERE album_id = ? ORDER BY track_number',
      [album.id]
    );

    return {
      ...track,
      album: {
        id: album.id,
        title: album.title,
        folder_name: album.folder_name,
        cover_thumb_url: album.cover_thumb_url,
        cover_medium_url: album.cover_medium_url,
        release_date: album.release_date,
        album_type: album.album_type,
      },
      otherTracks,
    };
  });

  /**
   * GET /api/albums/by-name/:name
   */
  fastify.get('/by-name/:name', {
    schema: {
      tags: ['albums'],
      summary: '앨범명으로 앨범 조회',
    },
  }, async (request, reply) => {
    const name = decodeURIComponent(request.params.name);

    const [albums] = await db.query(
      'SELECT * FROM albums WHERE folder_name = ? OR title = ?',
      [name, name]
    );

    if (albums.length === 0) {
      return reply.code(404).send({ error: '앨범을 찾을 수 없습니다.' });
    }

    return getAlbumDetails(albums[0]);
  });

  /**
   * GET /api/albums/:id
   */
  fastify.get('/:id', {
    schema: {
      tags: ['albums'],
      summary: 'ID로 앨범 조회',
    },
  }, async (request, reply) => {
    const [albums] = await db.query('SELECT * FROM albums WHERE id = ?', [
      request.params.id,
    ]);

    if (albums.length === 0) {
      return reply.code(404).send({ error: '앨범을 찾을 수 없습니다.' });
    }

    return getAlbumDetails(albums[0]);
  });

  // ==================== POST/PUT/DELETE (인증 필요) ====================

  /**
   * POST /api/albums
   */
  fastify.post('/', {
    schema: {
      tags: ['albums'],
      summary: '앨범 생성',
      security: [{ bearerAuth: [] }],
    },
    preHandler: [fastify.authenticate],
  }, async (request, reply) => {
    const parts = request.parts();
    let data = null;
    let coverBuffer = null;

    for await (const part of parts) {
      if (part.type === 'file' && part.fieldname === 'cover') {
        coverBuffer = await part.toBuffer();
      } else if (part.fieldname === 'data') {
        data = JSON.parse(part.value);
      }
    }

    if (!data) {
      return reply.code(400).send({ error: '데이터가 필요합니다.' });
    }

    const { title, album_type, album_type_short, release_date, folder_name, description, tracks } = data;

    if (!title || !album_type || !release_date || !folder_name) {
      return reply.code(400).send({ error: '필수 필드를 모두 입력해주세요.' });
    }

    const connection = await db.getConnection();

    try {
      await connection.beginTransaction();

      let coverOriginalUrl = null;
      let coverMediumUrl = null;
      let coverThumbUrl = null;

      if (coverBuffer) {
        const urls = await uploadAlbumCover(folder_name, coverBuffer);
        coverOriginalUrl = urls.originalUrl;
        coverMediumUrl = urls.mediumUrl;
        coverThumbUrl = urls.thumbUrl;
      }

      const [albumResult] = await connection.query(
        `INSERT INTO albums (title, album_type, album_type_short, release_date, folder_name,
                             cover_original_url, cover_medium_url, cover_thumb_url, description)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [title, album_type, album_type_short || null, release_date, folder_name,
         coverOriginalUrl, coverMediumUrl, coverThumbUrl, description || null]
      );

      const albumId = albumResult.insertId;

      if (tracks && tracks.length > 0) {
        for (const track of tracks) {
          await connection.query(
            `INSERT INTO album_tracks (album_id, track_number, title, duration, is_title_track,
                                 lyricist, composer, arranger, lyrics, music_video_url)
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
            [albumId, track.track_number, track.title, track.duration || null,
             track.is_title_track ? 1 : 0, track.lyricist || null, track.composer || null,
             track.arranger || null, track.lyrics || null, track.music_video_url || null]
          );
        }
      }

      await connection.commit();
      return { message: '앨범이 생성되었습니다.', albumId };
    } catch (error) {
      await connection.rollback();
      throw error;
    } finally {
      connection.release();
    }
  });

  /**
   * PUT /api/albums/:id
   */
  fastify.put('/:id', {
    schema: {
      tags: ['albums'],
      summary: '앨범 수정',
      security: [{ bearerAuth: [] }],
    },
    preHandler: [fastify.authenticate],
  }, async (request, reply) => {
    const { id } = request.params;
    const parts = request.parts();
    let data = null;
    let coverBuffer = null;

    for await (const part of parts) {
      if (part.type === 'file' && part.fieldname === 'cover') {
        coverBuffer = await part.toBuffer();
      } else if (part.fieldname === 'data') {
        data = JSON.parse(part.value);
      }
    }

    if (!data) {
      return reply.code(400).send({ error: '데이터가 필요합니다.' });
    }

    const { title, album_type, album_type_short, release_date, folder_name, description, tracks } = data;

    const connection = await db.getConnection();

    try {
      await connection.beginTransaction();

      const [existingAlbums] = await connection.query('SELECT * FROM albums WHERE id = ?', [id]);
      if (existingAlbums.length === 0) {
        return reply.code(404).send({ error: '앨범을 찾을 수 없습니다.' });
      }

      const existing = existingAlbums[0];
      let coverOriginalUrl = existing.cover_original_url;
      let coverMediumUrl = existing.cover_medium_url;
      let coverThumbUrl = existing.cover_thumb_url;

      if (coverBuffer) {
        const urls = await uploadAlbumCover(folder_name, coverBuffer);
        coverOriginalUrl = urls.originalUrl;
        coverMediumUrl = urls.mediumUrl;
        coverThumbUrl = urls.thumbUrl;
      }

      await connection.query(
        `UPDATE albums SET title = ?, album_type = ?, album_type_short = ?, release_date = ?,
                          folder_name = ?, cover_original_url = ?, cover_medium_url = ?,
                          cover_thumb_url = ?, description = ?
         WHERE id = ?`,
        [title, album_type, album_type_short || null, release_date, folder_name,
         coverOriginalUrl, coverMediumUrl, coverThumbUrl, description || null, id]
      );

      await connection.query('DELETE FROM album_tracks WHERE album_id = ?', [id]);

      if (tracks && tracks.length > 0) {
        for (const track of tracks) {
          await connection.query(
            `INSERT INTO album_tracks (album_id, track_number, title, duration, is_title_track,
                                 lyricist, composer, arranger, lyrics, music_video_url)
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
            [id, track.track_number, track.title, track.duration || null,
             track.is_title_track ? 1 : 0, track.lyricist || null, track.composer || null,
             track.arranger || null, track.lyrics || null, track.music_video_url || null]
          );
        }
      }

      await connection.commit();
      return { message: '앨범이 수정되었습니다.' };
    } catch (error) {
      await connection.rollback();
      throw error;
    } finally {
      connection.release();
    }
  });

  /**
   * DELETE /api/albums/:id
   */
  fastify.delete('/:id', {
    schema: {
      tags: ['albums'],
      summary: '앨범 삭제',
      security: [{ bearerAuth: [] }],
    },
    preHandler: [fastify.authenticate],
  }, async (request, reply) => {
    const { id } = request.params;
    const connection = await db.getConnection();

    try {
      await connection.beginTransaction();

      const [existingAlbums] = await connection.query('SELECT * FROM albums WHERE id = ?', [id]);
      if (existingAlbums.length === 0) {
        return reply.code(404).send({ error: '앨범을 찾을 수 없습니다.' });
      }

      const album = existingAlbums[0];

      if (album.cover_original_url && album.folder_name) {
        await deleteAlbumCover(album.folder_name);
      }

      await connection.query('DELETE FROM album_tracks WHERE album_id = ?', [id]);
      await connection.query('DELETE FROM albums WHERE id = ?', [id]);

      await connection.commit();
      return { message: '앨범이 삭제되었습니다.' };
    } catch (error) {
      await connection.rollback();
      throw error;
    } finally {
      connection.release();
    }
  });
}
