import 'package:flame/components.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:shitman/game/components/poop_bag.dart';
import 'package:shitman/game/components/house_components.dart';
import 'package:shitman/game/components/vision_cone.dart';
import 'package:shitman/game/components/base.dart';
import 'package:shitman/game/levels/operation_shitstorm.dart';
import 'package:shitman/game/input_manager.dart';
import 'package:shitman/settings/app_settings.dart';
import 'dart:math';

class Player extends InteractiveShit with Ambulatory, AppSettings {
  static const double speed = 100.0;
  static const double playerSize = 32.0;

  Vector2 velocity = Vector2.zero();
  bool hasPoopBag = true;
  bool isHidden = false;
  bool isCaught = false;
  double stealthLevel = 0.0; // 0.0 = fully visible, 1.0 = completely hidden
  PoopBag? placedPoopBag;
  VisionCone? playerVisionCone;
  double lastMovementDirection = 0.0;

  // Mission state
  bool isEscaping = false;
  double escapeTimeLimit = 30.0; // 30 seconds to escape
  double escapeTimeRemaining = 0.0;

  // Input manager for handling both keyboard and touch input
  final InputManager inputManager = InputManager();

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    await initSettings();

    // Create a simple colored rectangle as player
    size = Vector2.all(playerSize);
    position = Vector2(200, 200); // Start at center intersection

    // Create player vision cone
    playerVisionCone = VisionCone(
      origin: size / 2, // Relative to player center
      direction: lastMovementDirection,
      range: 80.0,
      fov: pi / 2, // 90 degrees
      color: Colors.blue,
      opacity: 0.0, // Start hidden
    );
    add(playerVisionCone!);

    appLog.fine('Player loaded at position $position');
  }

  void handleInput(Set<LogicalKeyboardKey> keysPressed) {
    // Don't handle input if caught
    if (isCaught) {
      velocity = Vector2.zero();
      inputManager.reset();
      return;
    }

    // Update input manager with keyboard input
    inputManager.setKeyboardMovement(keysPressed);

    // Apply movement from input manager
    final movement = inputManager.movementInput;
    velocity = movement * speed;
  }

  void handleAction(LogicalKeyboardKey key) {
    // Don't handle actions if caught
    if (isCaught) return;

    // Action controls
    if (key == LogicalKeyboardKey.space) {
      placePoop();
    }
    if (key == LogicalKeyboardKey.keyE) {
      ringDoorbell();
    }
  }

  /// Handle touch input from virtual controls
  void handleTouchMovement(Vector2 input) {
    if (isCaught) return;
    inputManager.setTouchMovement(input);

    // Apply movement from input manager
    final movement = inputManager.movementInput;
    velocity = movement * speed;
  }

  /// Handle touch actions
  void handleTouchPoopBag() {
    if (isCaught) return;
    placePoop();
  }

  void handleTouchDoorbell() {
    if (isCaught) return;
    ringDoorbell();
  }

  void updateStealthLevel(double dt) {
    // Simple stealth calculation - can be enhanced later
    // For now, player is more hidden when moving slowly or not at all
    if (velocity.length < 50) {
      stealthLevel = (stealthLevel + dt * 0.5).clamp(0.0, 1.0);
    } else {
      stealthLevel = (stealthLevel - dt * 1.5).clamp(0.0, 1.0);
    }

    isHidden = stealthLevel > 0.7;
  }

  void placePoop() {
    if (!hasPoopBag) return;

    appLog.fine('Placing poop bag at $position');

    // Create and place the poop bag
    placedPoopBag = PoopBag();
    placedPoopBag!.position =
        position + Vector2(playerSize / 2, playerSize + 10);
    game.world.add(placedPoopBag!);

    hasPoopBag = false;

    // Check if near target house
    checkMissionProgress();
  }

  void ringDoorbell() {
    appLog.fine('Attempting to ring doorbell');

    // Check if near any target house door
    final currentLevel =
        game.world.children.whereType<OperationShitstorm>().firstOrNull;
    if (currentLevel != null && currentLevel.isPlayerNearTarget(position)) {
      if (placedPoopBag != null) {
        // Light the poop bag on fire
        placedPoopBag!.lightOnFire();
        appLog.info('Ding dong! Poop bag is lit! RUN!');

        // Start escape timer - player has limited time to escape
        startEscapeSequence();
      } else {
        appLog.fine('Need to place poop bag first!');
      }
    } else {
      appLog.fine('Not near target house door');
    }
  }

  void startEscapeSequence() {
    appLog.info('Escape sequence started! Get to the edge of the map!');
    isEscaping = true;
    escapeTimeRemaining = escapeTimeLimit;

    // TODO: Show escape timer UI
    // TODO: Highlight escape routes on the map
  }

  /// Check if player is at an escape point (edge of the map)
  bool isAtEscapePoint() {
    const double escapeZoneThreshold = 50.0;

    // Check if near any edge of the level
    return position.x < escapeZoneThreshold ||
        position.y < escapeZoneThreshold ||
        position.x >
            (5 * 100) - escapeZoneThreshold || // 5x5 grid * 100 cell size
        position.y > (5 * 100) - escapeZoneThreshold;
  }

  void checkMissionProgress() {
    // Check if near target house and has placed poop bag
    final currentLevel =
        game.world.children.whereType<OperationShitstorm>().firstOrNull;
    final targetPos = currentLevel?.getTargetPosition();
    if (targetPos != null && placedPoopBag != null) {
      final distance = (position - targetPos).length;
      if (distance < 80) {
        appLog.fine('Near target house with poop bag placed!');
      }
    }
  }

  void getDetected() {
    appLog.warning('Player detected! Mission failed!');
    isCaught = true;
    velocity = Vector2.zero(); // Stop movement immediately
    game.failMission();
  }

  @override
  void update(double dt) {
    super.update(dt);

    // Apply movement
    if (velocity.length > 0) {
      velocity = velocity.normalized() * speed;
      position += velocity * dt;

      // Update movement direction for vision cone
      lastMovementDirection = atan2(velocity.y, velocity.x);

      // Keep player on screen (basic bounds checking)
      position.x = position.x.clamp(0, 800 - size.x);
      position.y = position.y.clamp(0, 600 - size.y);
    }

    // Update stealth level based on environment
    updateStealthLevel(dt);

    // Handle escape sequence
    if (isEscaping) {
      escapeTimeRemaining -= dt;

      // Check if time ran out
      if (escapeTimeRemaining <= 0) {
        appLog.warning('Time ran out! Mission failed!');
        getDetected();
        return;
      }

      // Check if player reached escape point (edge of map)
      if (isAtEscapePoint()) {
        appLog.info('Successfully escaped! Mission complete!');
        isEscaping = false;
        game.completeCurrentMission();
        return;
      }
    }

    // Check for detection by houses (only if not already caught)
    if (!isCaught) {
      checkForDetection();
    }

    // Update player vision cone
    if (playerVisionCone != null) {
      playerVisionCone!.updatePosition(size / 2, lastMovementDirection);

      // Update vision cone visibility based on settings
      try {
        final showVisionCones = appSettings.getBool('game.show_vision_cones');
        playerVisionCone!.updateOpacity(showVisionCones ? 0.2 : 0.0);
      } catch (e) {
        playerVisionCone!.updateOpacity(0.0); // Hide if settings not ready
      }
    }
  }

  void checkForDetection() {
    // Check for detection from houses in any active level
    final houses =
        game.world.children
            .expand((component) => component.children)
            .whereType<HouseComponent>();

    for (final house in houses) {
      if (house.detectsPlayer(position, stealthLevel)) {
        getDetected();
        break;
      }
    }
  }

  @override
  void render(Canvas canvas) {
    // Draw player as rectangle with color based on stealth level
    final playerPaint =
        Paint()
          ..color =
              isHidden
                  ? const Color(0xFF00FF00).withValues(
                    alpha: 0.7,
                  ) // Green when hidden
                  : const Color(
                    0xFF0000FF,
                  ).withValues(alpha: 0.9); // Blue when visible

    canvas.drawRect(size.toRect(), playerPaint);

    // Draw stealth indicator in debug mode
    try {
      final debugMode = appSettings.getBool('game.debug_mode');
      if (debugMode) {
        final stealthPaint =
            Paint()
              ..color =
                  Color.lerp(
                    const Color(0xFFFF0000),
                    const Color(0xFF00FF00),
                    stealthLevel,
                  )!;
        canvas.drawRect(Rect.fromLTWH(-5, -10, size.x + 10, 5), stealthPaint);
      }
    } catch (e) {
      // Continue without debug rendering if settings not available
    }
  }

  @override
  Future<void> reset() async {
    hasPoopBag = true;
    isHidden = false;
    isCaught = false;
    isEscaping = false;
    escapeTimeRemaining = 0.0;
    stealthLevel = 0.0;
    velocity = Vector2.zero();
    lastMovementDirection = 0.0;
    placedPoopBag = null;
    position = Vector2(200, 200); // Reset to starting position

    // Reset vision cone
    if (playerVisionCone != null) {
      await playerVisionCone!.reset();
      playerVisionCone!.updatePosition(size / 2, lastMovementDirection);
    }

    appLog.fine('Player reset to initial state');
  }
}
