class GamesController < ApplicationController
  include GamesHelper
  before_action :set_game, only: %i[ show edit update destroy join_game start_power_selection start_order_input turn_data vote_draw force_draw ]
  before_action :require_login, only: %i[ new create join_game ]
  before_action :require_game_admin, only: %i[ edit update destroy start_power_selection start_order_input ]

  helper_method :get_available_powers_for_select

  # GET /games or /games.json
  def index
    @recruiting_games = Game.where(status: "recruiting").includes(:participants)
    @my_games = current_user ? Game.joins(:participants).where(participants: { user_id: current_user.id }).includes(:participants, :turns) : []
    @games = Game.all.includes(:participants, :turns)
  end

  # GET /games/1 or /games/1.json
  def show
    @latest_turn = @game.turns.last

    # ゲーム終了判定
    @game_finished = @game.status == "finished"

    # 表示するターンの決定
    if @game_finished
      # 終了済みの場合:
      # params[:turn_number] があればそのターン
      # なければ 最初のターン (Turn 1) を表示
      if params[:turn_number].present?
        @display_turn = @game.turns.find_by(number: params[:turn_number].to_i)
      end

      # 指定がない、または見つからない場合は初期ターン(number=1)を表示
      # もし存在しなければ最新（というかあるやつ）
      @display_turn ||= @game.turns.find_by(number: 1) || @latest_turn

      # 最終結果の取得 (最後のターン情報から)
      if @latest_turn.game_state
         centers = @latest_turn.game_state["centers"] || {}
         alive_powers = centers.keys

         # ソロ勝利判定
         solo_winner = @game.solo_victory_power(@latest_turn.game_state)
         if solo_winner
           result_type = "Solo Victory"
           winners = [ solo_winner ]
         else
           result_type = "Draw"
           winners = alive_powers
         end

         @winner_info = {
           type: result_type,
           winners: winners,
           scores: @game.calculate_scores(@latest_turn.game_state)
         }
      end
    else
      # 進行中の場合: params[:turn_number] があればそのターン、なければ最新ターンを表示
      if params[:turn_number].present?
        @display_turn = @game.turns.find_by(number: params[:turn_number].to_i)
      end
      @display_turn ||= @latest_turn
    end

    if @display_turn
      @game_state = @display_turn.game_state

      # フェーズ名のパース
      @current_season_year = parse_phase(@display_turn.phase)

      # 国別情報の集計 (表示対象ターンのデータ)
      centers = @game_state["centers"] || {}
      units = @game_state["units"] || {}

      # 全7カ国（固定）
      powers = %w[AUSTRIA ENGLAND FRANCE GERMANY ITALY RUSSIA TURKEY]

      @country_statuses = powers.map do |power|
        participant = @game.participants.find_by(power: power)
        # 終了済みなら全員完了扱い、そうでなければターンごとの提出状況
        submitted = @game_finished ? true : @display_turn.orders_submitted_for?(power)

        {
          power: power,
          sc_count: centers[power]&.size || 0,
          unit_count: units[power]&.size || 0,
          submitted: submitted,
          participant: participant,
          is_user: current_user && participant&.user_id == current_user.id
        }
      end

      # 自国を先頭に移動
      if current_user
        user_power_index = @country_statuses.find_index { |s| s[:is_user] }
        if user_power_index
          user_status = @country_statuses.delete_at(user_power_index)
          @country_statuses.unshift(user_status)
        end
      end
    end
  end

  # GET /games/new
  def new
    @game = Game.new
    @game.is_solo_mode = current_user&.admin? ? false : false
  end

  # GET /games/1/edit
  def edit
  end

  # POST /games or /games.json
  def create
    @game = Game.new(game_params)

    # ソロモードかどうかを判定（管理者のみ選択可能）
    if current_user&.admin? && params.dig(:game, :game_mode) == "admin_mode"
      @game.is_solo_mode = true
    else
      @game.is_solo_mode = false
    end

    respond_to do |format|
      if @game.save
        # ゲーム作成者は自動的に参加者として登録（管理者として）
        Participant.create!(
          game: @game,
          user: current_user,
          is_administrator: true
        )

        # ソロモードの場合、即座に最初のターンを作成
        if @game.solo_mode?
          service = GameSetupService.new(@game)
          result = service.setup_initial_turn
          if result[:success]
            @game.update!(status: "in_progress")
          else
            # 失敗したらロールバックしたいところだが・・・
            # 現状はsave後なので、エラー表示だけにするかdestroyするか。
            # 今回は簡易的にログに残す
            logger.error result[:message]
          end
        end

        format.html { redirect_to @game, notice: "ゲームが正常に作成されました。" }
        format.json { render :show, status: :created, location: @game }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @game.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /games/1 or /games/1.json
  def update
    respond_to do |format|
      if @game.update(game_params)
        # スケジュール変更時にデッドラインを再計算
        if @game.status == "in_progress"
          @game.update_column(:next_deadline_at, @game.auto_turn? ? @game.calculate_next_deadline : nil)
        end
        format.html { redirect_to @game, notice: "ゲームが正常に更新されました。", status: :see_other }
        format.json { render :show, status: :ok, location: @game }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @game.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /games/1 or /games/1.json
  def destroy
    @game.destroy!

    respond_to do |format|
      format.html { redirect_to games_path, notice: "ゲームが正常に削除されました。", status: :see_other }
      format.json { head :no_content }
    end
  end

  # POST /games/1/join
  def join_game
    unless current_user
      redirect_to login_path, alert: "ゲームに参加するにはログインしてください"
      return
    end

    # パスワードチェック
    if @game.password_protected?
      password = params.dig(:participant, :password)
      unless @game.authenticate_password(password)
        redirect_to @game, alert: "パスワードが正しくありません"
        return
      end
    end

    # 既に参加しているかチェック
    if @game.participants.exists?(user: current_user)
      redirect_to @game, alert: "既にこのゲームに参加しています"
      return
    end

    # 満員チェック
    if @game.participants.count >= @game.participants_count
      redirect_to @game, alert: "このゲームは満員です"
      return
    end

    # 参加者を作成
    Participant.create!(
      game: @game,
      user: current_user
    )

    # 定員到達チェック
    if @game.participants.count == @game.participants_count
      @game.update(status: "power_selection")
    end

    redirect_to @game, notice: "ゲームに正常に参加しました！"
  end

  # POST /games/1/start_power_selection
  def start_power_selection
    unless @game.participants.count >= 2
      redirect_to @game, alert: "最低2人の参加者が必要です"
      return
    end

    @game.update!(status: "power_selection")
    redirect_to @game, notice: "国選択フェーズを開始しました！"
  end

  # POST /games/1/start_order_input
  def start_order_input
    unless @game.all_powers_assigned?
      redirect_to @game, alert: "全員が国を選択する必要があります"
      return
    end

    # 最初のターンを作成
    service = GameSetupService.new(@game)
    result = service.setup_initial_turn

    if result[:success]
      update_attrs = { status: "in_progress" }
      update_attrs[:next_deadline_at] = @game.calculate_next_deadline if @game.auto_turn?
      @game.update!(update_attrs)
      redirect_to @game, notice: "命令入力フェーズを開始しました！"
    else
      redirect_to @game, alert: result[:message]
    end
  end

  # GET /games/1/turn_data.json
  def turn_data
    if params[:turn_number].present?
      target_turn = @game.turns.find_by(number: params[:turn_number])
    end
    target_turn ||= @game.turns.last

    return head :not_found unless target_turn

    # 国別ステータス情報の再計算（JSON用）
    # showアクションと同様のロジック
    game_state = target_turn.game_state
    centers = game_state["centers"] || {}
    units = game_state["units"] || {}
    powers = %w[AUSTRIA ENGLAND FRANCE GERMANY ITALY RUSSIA TURKEY]

    country_statuses = powers.map do |power|
      # 終了済みなら全員完了扱い
      submitted = @game.status == "finished" ? true : target_turn.orders_submitted_for?(power)
      {
        power: power,
        sc_count: centers[power]&.size || 0,
        unit_count: units[power]&.size || 0,
        submitted: submitted
      }
    end

    render json: {
      turn_number: target_turn.number,
      phase: target_turn.phase,
      possible_orders: target_turn.possible_orders,
      decided_orders: target_turn.orders || {},
      svg_orders: target_turn.svg_orders || {},
      # svg_date カラムにデフォルトSVGが入っていると仮定（または svg_orders["NONE"]）
      # ここでは svg_date が単一の画像パスかSVG文字列かによるが、
      # 既存の show.html.erb 実装を見ると svg_orders["NONE"] を使っている可能性が高い
      # 既存実装: default_svg: last_turn.svg_date となっていたのでそのまま変更なしでいくが
      # target_turn.svg_date を返すようにする
      default_svg: target_turn.svg_date,

      # 完了状況
      all_orders_submitted: @game.status == "finished" || @game.all_orders_submitted?,
      missing_orders_powers: @game.status == "finished" ? [] : @game.participants.where(orders_submitted: false).pluck(:power).compact,
      country_statuses: country_statuses
    }
  end

  def vote_draw
    return unless @game.status == "in_progress"

    turn = @game.turns.last
    participant = @game.participants.find_by(user: current_user)

    unless participant && participant.power
      redirect_to @game, alert: "権限がありません。"
      return
    end

    power = participant.power
    if turn.draw_voted?(power)
      turn.revoke_draw_vote(power)
      flash[:notice] = "引き分け投票を取り消しました。"
    else
      turn.vote_draw(power)
      flash[:notice] = "引き分けに投票しました。"
    end

    if turn.unanimous_draw?
      if execute_draw(turn)
        flash[:notice] = "全会一致により、ゲームは引き分けとなりました。"
      else
        # エラーメッセージは execute_draw 内で flash[:alert] に設定される
      end
    end

    redirect_to @game
  end

  def force_draw
    return unless current_user.admin?

    turn = @game.turns.last
    if execute_draw(turn)
      redirect_to @game, notice: "ゲームを強制的に引き分けにしました。"
    else
      redirect_to @game
    end
  end

  private

  def execute_draw(turn)
    client = GameApiClient.new
    # 生存国を勝者として扱う（引き分け）
    winners = turn.powers
    begin
      response = client.api_game_draw(turn.game_state, winners: winners)

      if response
        # 新しいターン（完了状態）を作成
        Turn.create!(
          game: @game,
          number: turn.number + 1,
          # year, season カラムは存在しないため削除
          # phase を COMPLETED に設定
          game_state: response,
          orders: {},
          possible_orders: {},
          phase: "COMPLETED",
          svg_date: turn.svg_date,
          svg_orders: turn.svg_orders
        )
        @game.update(status: "finished")
        true
      else
        flash[:alert] = "ゲームサーバーからの応答が不正です。"
        false
      end
    rescue Faraday::ConnectionFailed => e
      flash[:alert] = "ゲームサーバーへの接続に失敗しました。管理者へ連絡してください。"
      Rails.logger.error "API Connection Failed: #{e.message}"
      false
    rescue Faraday::TimeoutError => e
      flash[:alert] = "ゲームサーバーとの通信がタイムアウトしました。"
      Rails.logger.error "API Timeout: #{e.message}"
      false
    rescue StandardError => e
      flash[:alert] = "予期せぬエラーが発生しました: #{e.message}"
      Rails.logger.error "Execute Draw Error: #{e.message}"
      false
    end
  end



  def set_game
    @game = Game.find(params.expect(:id))
  end

  def require_game_admin
    unless current_user&.admin? || @game.administrator == current_user
      redirect_to @game, alert: "ゲーム管理者のみこの機能にアクセスできます"
    end
  end

  def game_params
    house_rules = [ :year_limit, :victory_sc_count, :scoring_system, :turn_schedule ]

    if action_name == "update"
      params.expect(game: [ :title, :memo, :auto_order_mode ] + house_rules)
    else
      permitted = [ :title, :memo ] + house_rules

      if current_user&.admin?
        permitted += [ :participants_count, :password, :auto_order_mode ]
      else
        # 一般ユーザーはマルチプレイヤーモードのみ
        permitted += [ :participants_count, :password, :auto_order_mode ]
      end

      params.expect(game: permitted)
    end
  end
end
