using System;
using System.Collections.Generic;
using System.Linq;
using _PROJECT.Scripts.Bow;
using FishNet.Object;
using FishNet.Object.Synchronizing;
using TMPro;
using UnityEngine;
using Random = UnityEngine.Random;

public class ArcheryRange : NetworkBehaviour
{
    public TMP_Text highScoreText;
    public TMP_Text timeLeftText;
    public TMP_Text scoreText;

    public Transform targetStartPosition;
    public Transform targetEndPosition;
    public GameObject targetPrefab;
    public StartTarget startTarget;

    public Vector3 minRandomOffset = new Vector3(0f, -2f, -5f);
    public Vector3 maxRandomOffset = new Vector3(0f, 2f, 5f);
    public float roundLength = 60f;
    public float targetSpawnTime = 3f;

    private List<ArcheryTarget> _targets;
    
    [SyncVar]
    private float _score;
    private float _maxScore;
    private float _roundEndTime;
    private float _nextTargetTime;
    private bool _roundActive;

    public override void OnStartServer()
    {
        base.OnStartServer();
        _roundActive = false;
        _targets = new List<ArcheryTarget>();
        _score = 0;
        _maxScore = 0;
        _roundEndTime = 0f;
        SetHighScoreText("High Score: 0");
    }

    // Update is called once per frame
    void Update()
    {
        if (!IsServer) return;

        if (!_roundActive) return;

        if (Time.time >= _roundEndTime)
        {
            ResetRange();
        }
        else
        {
            SetTimeLeftText($"Time Left: {Math.Ceiling((_roundEndTime - Time.time) % 60)}");
            if (Time.time >= _nextTargetTime)
            {
                _nextTargetTime = Time.time + targetSpawnTime;
                SpawnTarget();
            }
        }
    }

    private void SpawnTarget()
    {
        if (!IsServer) return;
        
        var randomPos = targetStartPosition.position + new Vector3(
            Random.Range(minRandomOffset.x, maxRandomOffset.x),
            (float)Math.Round(Random.Range(minRandomOffset.y, maxRandomOffset.y)),
            Random.Range(minRandomOffset.z, maxRandomOffset.z));

        var target = SpawnTarget(randomPos);

        _targets.Add(target);
    }

    private ArcheryTarget SpawnTarget(Vector3 randomPos)
    {
        var prefab = Instantiate(targetPrefab, randomPos, Quaternion.identity, null);
        ArcheryTarget target = prefab.GetComponent<ArcheryTarget>();
        target.endPosition = targetEndPosition.position;
        target.addScore = AddScore;
        Spawn(prefab);
        return target;
    }


    public void ResetRange()
    {
        if (!IsServer) return;
        foreach (var target in _targets.Where(target => target != null))
        {
            Despawn(target.gameObject, DespawnType.Pool);
        }
        
        _targets = new List<ArcheryTarget>();
        if (_maxScore < _score) _maxScore = _score;
        _score = 0;
        SetHighScoreText($"High Score: {_maxScore}");
        startTarget.ShowTarget();
        _roundActive = false;
        SetTimeLeftText("");
    }

    public void StartRound()
    {
        if (!IsServer) return;
        _roundEndTime = Time.time + roundLength;
        _nextTargetTime = Time.time;
        _roundActive = true;
    }

    public void AddScore(float distance)
    {
        if (!IsServer) return;
        _score += distance;
        SetScoreText($"Score: {_score}");
    }

    [ObserversRpc]
    public void SetHighScoreText(string text)
    {
        highScoreText.text = text;
    }
    
    [ObserversRpc]
    public void SetScoreText(string text)
    {
        scoreText.text = text;
    }
    
    [ObserversRpc]
    public void SetTimeLeftText(string text)
    {
        timeLeftText.text = text;
    } 
}