// sdl_manager.cpp - Implementació del gestor SDL3
// © 2025 Port a C++20 amb SDL3

#include "sdl_manager.hpp"
#include "core/defaults.hpp"
#include "core/rendering/line_renderer.hpp"
#include "game/options.hpp"
#include "project.h"
#include <algorithm>
#include <format>
#include <iostream>

SDLManager::SDLManager()
    : finestra_(nullptr), renderer_(nullptr),
      current_width_(Defaults::Window::WIDTH),
      current_height_(Defaults::Window::HEIGHT), is_fullscreen_(false),
      max_width_(1920), max_height_(1080) {
  // Inicialitzar SDL3
  if (!SDL_Init(SDL_INIT_VIDEO)) {
    std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl;
    return;
  }

  // Calcular mida màxima des del display
  calculateMaxWindowSize();

  // Construir títol dinàmic igual que en pollo
  std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME,
                                         Project::VERSION, Project::COPYRIGHT);

  // Crear finestra CENTRADA (SDL ho fa automàticament amb CENTERED)
  finestra_ =
      SDL_CreateWindow(window_title.c_str(), current_width_, current_height_,
                       SDL_WINDOW_RESIZABLE // Permetre resize manual també
      );

  if (!finestra_) {
    std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl;
    SDL_Quit();
    return;
  }

  // IMPORTANT: Centrar explícitament la finestra
  SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED,
                        SDL_WINDOWPOS_CENTERED);

  // Crear renderer amb acceleració
  renderer_ = SDL_CreateRenderer(finestra_, nullptr);

  if (!renderer_) {
    std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl;
    SDL_DestroyWindow(finestra_);
    SDL_Quit();
    return;
  }

  // CRÍTIC: Configurar viewport scaling
  updateLogicalPresentation();

  std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_
            << " (logic: " << Defaults::Game::WIDTH << "x"
            << Defaults::Game::HEIGHT << ")" << std::endl;
}

// Constructor amb configuració
SDLManager::SDLManager(int width, int height, bool fullscreen)
    : finestra_(nullptr), renderer_(nullptr), current_width_(width),
      current_height_(height), is_fullscreen_(fullscreen), max_width_(1920),
      max_height_(1080) {
  // Inicialitzar SDL3
  if (!SDL_Init(SDL_INIT_VIDEO)) {
    std::cerr << "Error inicialitzant SDL3: " << SDL_GetError() << std::endl;
    return;
  }

  // Calcular mida màxima des del display
  calculateMaxWindowSize();

  // Construir títol dinàmic
  std::string window_title = std::format("{} v{} ({})", Project::LONG_NAME,
                                         Project::VERSION, Project::COPYRIGHT);

  // Configurar flags de la finestra
  SDL_WindowFlags flags = SDL_WINDOW_RESIZABLE;
  if (is_fullscreen_) {
    flags = static_cast<SDL_WindowFlags>(flags | SDL_WINDOW_FULLSCREEN);
  }

  // Crear finestra
  finestra_ = SDL_CreateWindow(window_title.c_str(), current_width_,
                               current_height_, flags);

  if (!finestra_) {
    std::cerr << "Error creant finestra: " << SDL_GetError() << std::endl;
    SDL_Quit();
    return;
  }

  // Centrar explícitament la finestra (si no és fullscreen)
  if (!is_fullscreen_) {
    SDL_SetWindowPosition(finestra_, SDL_WINDOWPOS_CENTERED,
                          SDL_WINDOWPOS_CENTERED);
  }

  // Crear renderer amb acceleració
  renderer_ = SDL_CreateRenderer(finestra_, nullptr);

  if (!renderer_) {
    std::cerr << "Error creant renderer: " << SDL_GetError() << std::endl;
    SDL_DestroyWindow(finestra_);
    SDL_Quit();
    return;
  }

  // Configurar viewport scaling
  updateLogicalPresentation();

  std::cout << "SDL3 inicialitzat: " << current_width_ << "x" << current_height_
            << " (logic: " << Defaults::Game::WIDTH << "x"
            << Defaults::Game::HEIGHT << ")";
  if (is_fullscreen_) {
    std::cout << " [FULLSCREEN]";
  }
  std::cout << std::endl;
}

SDLManager::~SDLManager() {
  if (renderer_) {
    SDL_DestroyRenderer(renderer_);
    renderer_ = nullptr;
  }

  if (finestra_) {
    SDL_DestroyWindow(finestra_);
    finestra_ = nullptr;
  }

  SDL_Quit();
  std::cout << "SDL3 netejat correctament" << std::endl;
}

void SDLManager::calculateMaxWindowSize() {
  SDL_DisplayID display = SDL_GetPrimaryDisplay();
  const SDL_DisplayMode *mode = SDL_GetCurrentDisplayMode(display);

  if (mode) {
    // Deixar marge de 100px per a decoracions de l'OS
    max_width_ = mode->w - 100;
    max_height_ = mode->h - 100;
    std::cout << "Display detectat: " << mode->w << "x" << mode->h
              << " (max finestra: " << max_width_ << "x" << max_height_ << ")"
              << std::endl;
  } else {
    // Fallback conservador
    max_width_ = 1920;
    max_height_ = 1080;
    std::cerr << "No s'ha pogut detectar el display, usant fallback: "
              << max_width_ << "x" << max_height_ << std::endl;
  }
}

void SDLManager::updateLogicalPresentation() {
  // AIXÒ ÉS LA MÀGIA: El joc SEMPRE dibuixa en 640x480,
  // SDL escala automàticament a la mida física de la finestra
  SDL_SetRenderLogicalPresentation(
      renderer_,
      Defaults::Game::WIDTH,             // 640 (lògic)
      Defaults::Game::HEIGHT,            // 480 (lògic)
      SDL_LOGICAL_PRESENTATION_LETTERBOX // Mantenir aspect ratio 4:3
  );
}

void SDLManager::increaseWindowSize() {
  if (is_fullscreen_)
    return; // No operar en fullscreen

  int new_width = current_width_ + Defaults::Window::SIZE_INCREMENT;
  int new_height = current_height_ + Defaults::Window::SIZE_INCREMENT;

  // Clamp a màxim
  new_width = std::min(new_width, max_width_);
  new_height = std::min(new_height, max_height_);

  if (new_width != current_width_ || new_height != current_height_) {
    applyWindowSize(new_width, new_height);

    // Persistir canvis a Options (es guardarà a config.yaml al tancar)
    Options::window.width = current_width_;
    Options::window.height = current_height_;

    std::cout << "F2: Finestra augmentada a " << new_width << "x" << new_height
              << std::endl;
  }
}

void SDLManager::decreaseWindowSize() {
  if (is_fullscreen_)
    return;

  int new_width = current_width_ - Defaults::Window::SIZE_INCREMENT;
  int new_height = current_height_ - Defaults::Window::SIZE_INCREMENT;

  // Clamp a mínim
  new_width = std::max(new_width, Defaults::Window::MIN_WIDTH);
  new_height = std::max(new_height, Defaults::Window::MIN_HEIGHT);

  if (new_width != current_width_ || new_height != current_height_) {
    applyWindowSize(new_width, new_height);

    // Persistir canvis a Options (es guardarà a config.yaml al tancar)
    Options::window.width = current_width_;
    Options::window.height = current_height_;

    std::cout << "F1: Finestra reduïda a " << new_width << "x" << new_height
              << std::endl;
  }
}

void SDLManager::applyWindowSize(int new_width, int new_height) {
  // Obtenir posició actual ABANS del resize
  int old_x, old_y;
  SDL_GetWindowPosition(finestra_, &old_x, &old_y);

  int old_width = current_width_;
  int old_height = current_height_;

  // Actualitzar mida
  SDL_SetWindowSize(finestra_, new_width, new_height);
  current_width_ = new_width;
  current_height_ = new_height;

  // CENTRADO INTEL·LIGENT (algoritme de pollo)
  // Calcular nova posició per mantenir la finestra centrada sobre si mateixa
  int delta_width = old_width - new_width;
  int delta_height = old_height - new_height;

  int new_x = old_x + (delta_width / 2);
  int new_y = old_y + (delta_height / 2);

  // Evitar que la finestra surti de la pantalla
  constexpr int TITLEBAR_HEIGHT = 35; // Alçada aproximada de la barra de títol
  new_x = std::max(new_x, 0);
  new_y = std::max(new_y, TITLEBAR_HEIGHT);

  SDL_SetWindowPosition(finestra_, new_x, new_y);

  // NO cal actualitzar el logical presentation aquí,
  // SDL ho maneja automàticament
}

void SDLManager::toggleFullscreen() {
  is_fullscreen_ = !is_fullscreen_;
  SDL_SetWindowFullscreen(finestra_, is_fullscreen_);

  // Persistir canvis a Options (es guardarà a config.yaml al tancar)
  Options::window.fullscreen = is_fullscreen_;

  std::cout << "F3: Fullscreen " << (is_fullscreen_ ? "activat" : "desactivat")
            << std::endl;

  // En fullscreen, SDL gestiona tot automàticament
  // En sortir, restaura la mida anterior
}

bool SDLManager::handleWindowEvent(const SDL_Event &event) {
  if (event.type == SDL_EVENT_WINDOW_RESIZED) {
    // Usuari ha redimensionat manualment (arrossegar vora)
    // Actualitzar el nostre tracking
    SDL_GetWindowSize(finestra_, &current_width_, &current_height_);
    std::cout << "Finestra redimensionada manualment a " << current_width_
              << "x" << current_height_ << std::endl;
    return true;
  }
  return false;
}

void SDLManager::neteja(uint8_t r, uint8_t g, uint8_t b) {
  if (!renderer_)
    return;

  // [MODIFICAT] Usar color oscil·lat del fons en lloc dels paràmetres
  (void)r;
  (void)g;
  (void)b; // Suprimir warnings
  SDL_Color bg = color_oscillator_.getCurrentBackgroundColor();
  SDL_SetRenderDrawColor(renderer_, bg.r, bg.g, bg.b, 255);
  SDL_RenderClear(renderer_);
}

void SDLManager::presenta() {
  if (!renderer_)
    return;

  SDL_RenderPresent(renderer_);
}

// [NUEVO] Actualitzar colors amb oscil·lació
void SDLManager::updateColors(float delta_time) {
  color_oscillator_.update(delta_time);

  // Actualitzar color global de línies
  Rendering::setLineColor(color_oscillator_.getCurrentLineColor());
}
