using System.Security.Claims;
using JobsMedical.Web.Data;
using JobsMedical.Web.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;

namespace JobsMedical.Web.Pages.Facilities;

public class DetailsModel : PageModel
{
    private readonly AppDbContext _db;
    private readonly JobsMedical.Web.Services.Scraping.SettingsService _settings;

    public DetailsModel(AppDbContext db, JobsMedical.Web.Services.Scraping.SettingsService settings)
    {
        _db = db;
        _settings = settings;
    }

    public Facility? Facility { get; private set; }
    public List<Shift> Shifts { get; private set; } = new();
    public List<JobOpening> Jobs { get; private set; } = new();
    public string? MapKey { get; private set; }
    public bool Reported { get; private set; }

    public record ReviewRow(string Who, int Stars, string? Comment, DateTime When);
    public List<ReviewRow> Reviews { get; private set; } = new();
    public double AvgRating { get; private set; }
    public int RatingCount { get; private set; }
    public bool CanReview { get; private set; }      // logged in & not yet reviewed
    public bool AlreadyReviewed { get; private set; }
    [TempData] public string? ReviewMsg { get; set; }

    public async Task<IActionResult> OnGetAsync(int id)
    {
        Facility = await _db.Facilities.Include(f => f.City).Include(f => f.District)
            .FirstOrDefaultAsync(f => f.Id == id);
        if (Facility is null) return NotFound();

        var today = DateOnly.FromDateTime(DateTime.UtcNow);
        Shifts = await _db.Shifts.Include(s => s.Role)
            .Where(s => s.FacilityId == id && s.Status == ShiftStatus.Open && s.Date >= today)
            .OrderBy(s => s.Date).Take(12).ToListAsync();
        Jobs = await _db.JobOpenings.Include(j => j.Role)
            .Where(j => j.FacilityId == id && j.Status == ShiftStatus.Open)
            .OrderByDescending(j => j.CreatedAt).Take(12).ToListAsync();

        MapKey = (await _settings.GetAsync()).NeshanMapKey;
        Reported = Request.Query["reported"] == "1";

        await LoadReviewsAsync(id);
        return Page();
    }

    public async Task<IActionResult> OnPostReviewAsync(int id, int stars, string? comment)
    {
        if (User.Identity?.IsAuthenticated != true)
            return RedirectToPage("/Account/Login", new { returnUrl = $"/Facilities/Details/{id}" });

        var uid = int.Parse(User.FindFirstValue(System.Security.Claims.ClaimTypes.NameIdentifier)!);
        if (!await _db.Facilities.AnyAsync(f => f.Id == id)) return NotFound();
        stars = Math.Clamp(stars, 1, 5);

        var existing = await _db.Reviews.FirstOrDefaultAsync(r => r.FacilityId == id && r.UserId == uid);
        if (existing is null)
            _db.Reviews.Add(new Review { FacilityId = id, UserId = uid, Stars = stars, Comment = comment?.Trim() });
        else { existing.Stars = stars; existing.Comment = comment?.Trim(); existing.CreatedAt = DateTime.UtcNow; }
        await _db.SaveChangesAsync();
        ReviewMsg = "نظر شما ثبت شد. متشکریم.";
        return RedirectToPage(new { id });
    }

    private async Task LoadReviewsAsync(int id)
    {
        var rows = await _db.Reviews.Include(r => r.User)
            .Where(r => r.FacilityId == id && r.IsApproved)
            .OrderByDescending(r => r.CreatedAt).ToListAsync();
        RatingCount = rows.Count;
        AvgRating = rows.Count > 0 ? Math.Round(rows.Average(r => r.Stars), 1) : 0;
        Reviews = rows.Take(20).Select(r => new ReviewRow(
            r.User.FullName ?? "کاربر", r.Stars, r.Comment, r.CreatedAt)).ToList();

        if (User.Identity?.IsAuthenticated == true &&
            int.TryParse(User.FindFirstValue(System.Security.Claims.ClaimTypes.NameIdentifier), out var uid))
        {
            AlreadyReviewed = rows.Any(r => r.UserId == uid)
                || await _db.Reviews.AnyAsync(r => r.FacilityId == id && r.UserId == uid);
            CanReview = true;
        }
    }
}
