const response = require('../../../helpers/responses')
const db = require('../../../../models/migration')
const errorHandler = require('../../../middlewares/errorHandler')
const { sequelize, Op } = require('../../../../models/migration')

const User = db.User
const path = require("path");
const fs = require("fs");
const Story = db.Story;
const StoryReader = db.StoryReader
const Serial = db.Serial;
const StoryRating = db.StoryRating
const StoryLike = db.StoryLike
const Category = db.Category;
const DifficultyLevel = db.DifficultyLevel
const AgeTarget = db.AgeTarget



// UPDATE
const update = async (req, res) => {
  const t = await sequelize.transaction();
  try {
    const id = req.user.id;

    const users = await User.findOne({
      where: { id },
      transaction: t,
    });

    if (!users) {
      await t.rollback();
      return response.failed(res, 404, "User tidak ditemukan atau bukan milik Anda");
    }

    const body = req.body;
    let avatarUrl = users.avatar_url; // default tetap avatar lama

    // 🔹 Kalau ada file diupload
    if (req.file) {
      const uploadDir = path.join(process.cwd(), "public", "uploads", "avatars");
      if (!fs.existsSync(uploadDir)) {
        fs.mkdirSync(uploadDir, { recursive: true });
      }

      // Simpan file
      const fileName = `${Date.now()}-${req.file.originalname}`;
      const filePath = path.join(uploadDir, fileName);
      fs.writeFileSync(filePath, req.file.buffer);

      // Bisa pakai URL public (misal /uploads/avatars/xxx.jpg)
      avatarUrl = `/uploads/avatars/${fileName}`;
    }

    const updatedUser = await users.update(
      {
        ...body,
        avatar_url: avatarUrl,
      },
      { transaction: t }
    );

    await t.commit();

    return response.success(res, updatedUser, "Profil berhasil diperbarui");
  } catch (error) {
    await t.rollback();
    errorHandler(error, req, res);
    return response.failed(res, 500, error.message);
  }
};

// GET ALL
const getProfile = async (req, res) => {
  try {
    const user_id = req.user.id

    const user = await User.findOne({
      where: { id: user_id }
    })

    if (!user) {
      return response.failed(res, 404, 'User tidak ditemukan')
    }

    // Mapper agar sesuai response yang kamu mau
    const result = {
      id: user.id,
      email: user.email,
      display_name: user.name, // atau field display_name jika ada
      role: user.role,
      avatar_url: user.avatar_url || null,
      bio: user.bio || null,
      birth: user.birth || null,
      created_at: user.created_at,
      updated_at: user.updated_at
    }

    return response.success(res, result, 'Profile berhasil dimuat')
  } catch (error) {
    errorHandler(error, req, res)
    return response.failed(res, 500, error.message)
  }
}


const getOverview = async (req, res) => {
  try {
    const user_id = req.user.id;

    // Total cerita
    const totalStories = await Story.count({ where: { user_id } });
    const totalPublished = await Story.count({ where: { user_id, is_published: true } });

    // Total pembaca unik
    const totalReaders = await StoryReader.count({
      include: [{ model: Story, where: { user_id }, attributes: [] }],
      distinct: true,
      col: "user_id"
    });

    // Rating rata-rata (FIX: kualifikasi kolom supaya tidak ambiguous)
    const ratingResult = await StoryRating.findOne({
      attributes: [
        [sequelize.fn("AVG", sequelize.col("StoryRating.rating")), "avgRating"]
      ],
      include: [{ model: Story, where: { user_id }, attributes: [] }],
      raw: true
    });
    const avgRating = ratingResult && ratingResult.avgRating
      ? Number(parseFloat(ratingResult.avgRating).toFixed(1))
      : 0;

    // === Ambil semua serial user ===
    const serialsRaw = await Serial.findAll({
      where: { user_id },
      attributes: [
        "id",
        "title",
        "description",
        "reading_time",
        "rating",
        "cover_image_url",
        "createdAt",
        "is_active"
      ],
      include: [{ model: Category, attributes: ["id", "title", "emoji"] }],
      order: [["createdAt", "DESC"]]
    });

    // Ambil semua story user (sekalian untuk lookup cover)
    const stories = await Story.findAll({
      where: { user_id },
      attributes: [
        "id",
        "title",
        "synopsis",
        "is_published",
        "cover_image_url",
        "createdAt",
        "series_id"
      ],
      include: [
        { model: Category, attributes: ["id", "title", "emoji"] },
        { model: DifficultyLevel, attributes: ["id", "title", "emoji"] },
        { model: AgeTarget, attributes: ["id", "title", "emoji"] }
      ],
      order: [["createdAt", "DESC"]]
    });

    // Buat map serial_id → serial
    const serialMap = {};
    serialsRaw.forEach(serial => {
      serialMap[serial.id] = serial.toJSON();
    });

    // Buat map serial_id → story pertama (untuk fallback cover)
    const storiesBySerial = {};
    for (const story of stories) {
      if (story.series_id && !storiesBySerial[story.series_id]) {
        storiesBySerial[story.series_id] = story.cover_image_url;
      }
    }

    // === Gabungkan serial dengan fallback cover ===
    const serials = serialsRaw.map(serial => {
      let coverImage = serial.cover_image_url;
      if (!coverImage && storiesBySerial[serial.id]) {
        coverImage = storiesBySerial[serial.id];
      }

      const storiesOfSerial = stories.filter(s => s.series_id === serial.id);

      return {
        id: serial.id,
        title: serial.title,
        description: serial.description,
        reading_time: serial.reading_time,
        rating: serial.rating,
        cover_image_url: coverImage,
        is_active: serial.is_active,
        createdAt: serial.createdAt,
        category: serial.Category
          ? { id: serial.Category.id, title: serial.Category.title, emoji: serial.Category.emoji }
          : null,
        story: storiesOfSerial.map(s => ({
          id: s.id,
          title: s.title,
          cover_image_url: s.cover_image_url,
          is_published: s.is_published
        })),
        total_episodes: storiesOfSerial.length
      };
    });

    // === Gabungkan story dengan serial data ===
    const storiesWithSerial = stories.map(story => {
      const serial = story.series_id ? serialMap[story.series_id] || null : null;
      let coverImage = story.cover_image_url;

      // Fallback cover dari serial
      if (!coverImage && serial) {
        coverImage = serial.cover_image_url || storiesBySerial[serial.id] || null;
      }

      return {
        ...story.toJSON(),
        cover_image_url: coverImage,
        Serial: serial
      };
    });

    // === Response ===
    return response.success(
      res,
      {
        total_stories: totalStories,
        total_published: totalPublished,
        total_readers: totalReaders,
        average_rating: avgRating,
        stories: storiesWithSerial,
        serials
      },
      "Overview berhasil dimuat"
    );
  } catch (error) {
    errorHandler(error, req, res);
    return response.failed(res, 500, error.message);
  }
};







module.exports = {
  update,
  getProfile,
  getOverview
}
