using Microsoft.AspNetCore.Mvc;
using PSTW_CentralSystem.DBContext;
using PSTW_CentralSystem.Areas.MMS.Models;
using System.IO;
using System.Linq;
using PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator;
using QuestPDF.Fluent;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using MySqlConnector;

namespace PSTW_CentralSystem.Areas.MMS.Controllers
{
    public class TarballPdfDto
    {
        // From tbl_marine_tarball
        public int Id { get; set; }
        public string StationID { get; set; }
        public string Longitude { get; set; }
        public string Latitude { get; set; }
        public DateTime DateSample { get; set; }
        public TimeSpan TimeSample { get; set; }
        public string ClassifyID { get; set; }
        public string OptionalName1 { get; set; }
        public string OptionalName2 { get; set; }
        public string OptionalName3 { get; set; }
        public string OptionalName4 { get; set; }
        public string FirstSampler { get; set; }

        // From joined tables
        public string LocationName { get; set; }  // From tbl_marine_station
        public string StateName { get; set; }     // From tbl_state
        public string FullName { get; set; }      // From tbl_user
        public string LevelName { get; set; }     // From tbl_level
    }

    [Area("MMS")]
    public class MarineController : Controller
    {
        private readonly MMSSystemContext _context;//Used in TarBallForm and GeneratePdfResponse to query the database.
        private readonly NetworkShareAccess _networkAccessService;//used in GetImage and GeneratePdfResponse
        private const string PhotoBasePath = @"\\192.168.12.42\images\marine\manual_tarball";//used in GetImage and GeneratePdfResponse

        public MarineController(MMSSystemContext context, NetworkShareAccess networkAccessService)
        {
            _context = context;
            _networkAccessService = networkAccessService;
        }

        public IActionResult Index()
        {
            return View();
        }

        public IActionResult TarBallForm()//Queries the database and returns a view with tarball data
        {
            try
            {
                var marineTarballs = _context.MarineTarballs //ERRORRRRRRR======================================
                    .Select(t => new
                    {
                        t.Id,
                        Date = t.DateSample.ToString("yyyy/MM/dd"),
                        Station = t.StationID
                    })
                    .ToList();

                Console.WriteLine($"Marine Tarballs Count: {marineTarballs.Count}");
                return View(marineTarballs);
            }
            catch (Exception ex)
            {
                // Show the real error in the browser (for debugging only)
                return Content($"Error: {ex.Message}<br/>{ex.StackTrace}", "text/html");
            }

        }

        [HttpGet] // Explicitly mark as a GET endpoint
        public IActionResult TestCredentials()
        {
            try
            {
                // Use the EXACT same path/credentials as in Program.cs
                var testService = new NetworkShareAccess(
                    @"\\192.168.12.42\images\marine\manual_tarball",
                    "installer",
                    "mms@pstw"
                );

                testService.ConnectToNetworkPath();
                testService.DisconnectFromNetworkShare();

                return Ok("Network credentials and path are working correctly!");
            }
            catch (Exception ex)
            {
                // Log the full error (including stack trace)
                Console.WriteLine($"TestCredentials failed: {ex}");
                return StatusCode(500, $"Credentials test failed: {ex.Message}");
            }
        }

        public IActionResult GetImage(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                return BadRequest("Filename cannot be empty");
            }

            // Sanitize filename to prevent path traversal attacks
            var sanitizedFileName = Path.GetFileName(fileName);
            if (sanitizedFileName != fileName)
            {
                return BadRequest("Invalid filename");
            }

            int retryCount = 0;
            const int maxRetries = 3;
            bool connectionSuccess = false;

            // Retry loop for network connection
            while (retryCount < maxRetries && !connectionSuccess)
            {
                try
                {
                    Console.WriteLine($"Attempt {retryCount + 1} to connect to network share...");

                    // Connect to network share
                    _networkAccessService.ConnectToNetworkPath();
                    connectionSuccess = true;

                    Console.WriteLine("Network share connected successfully");
                }
                catch (Exception ex)
                {
                    retryCount++;
                    Console.WriteLine($"Connection attempt {retryCount} failed: {ex.Message}");

                    if (retryCount >= maxRetries)
                    {
                        Console.WriteLine($"Max connection attempts reached. Last error: {ex}");
                        return StatusCode(503, $"Could not establish connection to image server after {maxRetries} attempts");
                    }

                    // Wait before retrying (1s, 2s, 3s)
                    Thread.Sleep(1000 * retryCount);
                }
            }

            try
            {
                string imagePath = Path.Combine(PhotoBasePath, sanitizedFileName);
                Console.WriteLine($"Attempting to access image at: {imagePath}");

                // Verify file exists
                if (!System.IO.File.Exists(imagePath))
                {
                    Console.WriteLine($"Image not found at path: {imagePath}");
                    return NotFound($"Image '{sanitizedFileName}' not found on server");
                }

                // Verify file is an image
                if (!IsImageValid(imagePath))
                {
                    Console.WriteLine($"Invalid image file at path: {imagePath}");
                    return BadRequest("The requested file is not a valid image");
                }

                // Read and return the image
                byte[] imageBytes = System.IO.File.ReadAllBytes(imagePath);
                Console.WriteLine($"Successfully read image: {sanitizedFileName} ({imageBytes.Length} bytes)");

                // Determine content type based on extension
                string contentType = "image/jpeg"; // default
                string extension = Path.GetExtension(sanitizedFileName)?.ToLower();

                if (extension == ".png")
                {
                    contentType = "image/png";
                }
                else if (extension == ".gif")
                {
                    contentType = "image/gif";
                }

                return File(imageBytes, contentType);
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine($"Access denied to image: {ex}");
                return StatusCode(403, "Access to the image was denied");
            }
            catch (IOException ex)
            {
                Console.WriteLine($"IO error accessing image: {ex}");
                return StatusCode(503, "Error accessing image file");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Unexpected error: {ex}");
                return StatusCode(500, "An unexpected error occurred while processing the image");
            }
            finally
            {
                try
                {
                    if (connectionSuccess)
                    {
                        Console.WriteLine("Disconnecting from network share...");
                        _networkAccessService.DisconnectFromNetworkShare();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Warning: Error disconnecting from share: {ex.Message}");
                    // Don't fail the request because of disconnect issues
                }
            }
        }

        public async Task<IActionResult> GenerateReport(int id)//calls GeneratePdfResponse to generate a PDF for inline viewing
        {
            return await GeneratePdfResponse(id, true);
        }

        public async Task<IActionResult> DownloadPDF(int id)
        {
            return await GeneratePdfResponse(id, true);
        }


        public IActionResult ViewPDF(int id)
        {
            try
            {
                // Add timeout for safety
                var task = Task.Run(() => GeneratePdfResponse(id, false));
                if (task.Wait(TimeSpan.FromSeconds(30))) // 30 second timeout
                {
                    return task.Result;
                }
                return StatusCode(500, "PDF generation took too long");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"PDF VIEW ERROR: {ex}");
                return StatusCode(500, $"Error showing PDF: {ex.Message}");
            }
        }

        private async Task<IActionResult> GeneratePdfResponse(int id, bool forceDownload)
        {
            Console.WriteLine($"Requested ID in {(forceDownload ? "GenerateReport" : "ViewPDF")}: {id}");

            // Temporary network connection test
            try
            {
                Console.WriteLine("Testing network connection...");
                _networkAccessService.ConnectToNetworkPath();
                Console.WriteLine("Network connected successfully!");
                _networkAccessService.DisconnectFromNetworkShare();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"NETWORK ERROR: {ex.Message}");
                return StatusCode(500, $"Cannot access network: {ex.Message}");
            }

            try
            {
                // Connect to the network path
                _networkAccessService.ConnectToNetworkPath();

                // ===== 1. NEW SQL QUERY APPROACH =====
                var query = @"
                SELECT 
                    marine.*, 
                    station.LocationName, 
                    state.StateName,
                user.FullName,level.LevelName
                FROM tbl_marine_tarball marine
                JOIN tbl_marine_station station ON marine.StationID = station.StationID
                JOIN tbl_state state ON station.StateID = state.StateID
                JOIN tbl_user user ON marine.FirstSampler = user.FullName  -- Corrected column name
                JOIN tbl_level level ON user.LevelID = level.LevelID
                WHERE marine.Id = @id";

                var tarball = await _context.Database
                    .SqlQueryRaw<TarballPdfDto>(query, new MySqlParameter("@id", id))
                    .FirstOrDefaultAsync();

                if (tarball == null)
                    return NotFound("Record not found");

                //Prepare boolean values for PDF 
                bool tarBallYes = tarball.ClassifyID != "NO";
                bool tarBallNo = tarball.ClassifyID == "NO";
                bool isSand = tarball.ClassifyID == "SD";
                bool isNonSandy = tarball.ClassifyID == "NS";
                bool isCoquina = tarball.ClassifyID == "CO";

                // ===== 2. Get Images from path =====
                var sampleDateString = tarball.DateSample.ToString("yyyyMMdd");
                //var sampleTimeString = tarball.TimeSample.ToString("hhmmss");
                var sampleTimePrefix = ((int)tarball.TimeSample.TotalHours).ToString("D2") +
                       tarball.TimeSample.Minutes.ToString("D2");
                var stationFolder = Path.Combine(PhotoBasePath, tarball.StationID);

                //Image collection
                var stationImages = new Dictionary<string, string>();

                if (Directory.Exists(stationFolder))
                {
                    var imageTypes = new Dictionary<string, string>
                    {
                        { "LEFTSIDECOASTALVIEW", null },
                        { "RIGHTSIDECOASTALVIEW", null },
                        { "DRAWINGVERTICALLINES", null },
                        { "DRAWINGHORIZONTALLINES", null },
                        { "OPTIONAL01", null },  // Will remain null if not found
                        { "OPTIONAL02", null },
                        { "OPTIONAL03", null },
                        { "OPTIONAL04", null }
                    };

                    foreach (var imagePath in Directory.GetFiles(stationFolder))
                    {
                        var fileName = Path.GetFileNameWithoutExtension(imagePath);
                        foreach (var type in imageTypes.Keys.ToList())
                        {
                            if (fileName.EndsWith(type, StringComparison.OrdinalIgnoreCase))
                            {
                                imageTypes[type] = imagePath;
                                break;
                            }
                        }
                    }
                    stationImages = imageTypes;
                }
                //Mandatory images
                var mandatoryImages = new List<string>
                {
                    "LEFTSIDECOASTALVIEW",
                    "RIGHTSIDECOASTALVIEW",
                    "DRAWINGVERTICALLINES",
                    "DRAWINGHORIZONTALLINES"
                };

                foreach(var mandatoryType in mandatoryImages)
                {
                    if(!stationImages.ContainsKey(mandatoryType))
                    {
                        return StatusCode(400, $"Missing mandatory image: {mandatoryType}");
                    }
                }

                // ===== 3. GENERATE PDF (ADAPTED FOR NEW DTO) =====
                var pdf = new TarBallPDF(
                    tarball.StateName,
                    tarball.StationID,
                    tarball.LocationName,
                    tarball.Longitude,
                    tarball.Latitude,
                    tarball.DateSample,
                    tarball.TimeSample,
                    tarball.ClassifyID,
                    tarBallYes,
                    tarBallNo,
                    isSand,
                    isNonSandy,
                    isCoquina,
                    stationImages["LEFTSIDECOASTALVIEW"],
                    stationImages["RIGHTSIDECOASTALVIEW"],
                    stationImages["DRAWINGVERTICALLINES"],
                    stationImages["DRAWINGHORIZONTALLINES"],
                    stationImages.GetValueOrDefault("OPTIONAL01"),
                    stationImages.GetValueOrDefault("OPTIONAL02"),
                    stationImages.GetValueOrDefault("OPTIONAL03"),
                    stationImages.GetValueOrDefault("OPTIONAL04"),
                    tarball.OptionalName1,
                    tarball.OptionalName2,
                    tarball.OptionalName3,
                    tarball.OptionalName4,
                    tarball.FirstSampler,
                    tarball.FullName,
                    tarball.LevelName
                ).GeneratePdf();

                return forceDownload
                    ? File(pdf, "application/pdf", $"{tarball.StationID}_{tarball.DateSample:yyyyMMdd}_{tarball.TimeSample:hhmmss}.pdf")
                    : File(pdf, "application/pdf");
            }
            catch (Exception ex)
            {
                var errorMessage = ex.InnerException != null
                    ? $"{ex.Message} (Inner: {ex.InnerException.Message})"
                    : ex.Message;
                return Content($"PDF generation failed: {errorMessage}<br/>{ex.StackTrace}", "text/html");
            }
            finally
            {
                _networkAccessService.DisconnectFromNetworkShare();
            }
        }

        private bool IsImageValid(string imagePath)
        {
            try
            {
                using (var image = System.Drawing.Image.FromFile(imagePath))
                    return true;
            }
            catch
            {
                Console.WriteLine($"Invalid image skipped: {imagePath}");
                return false;
            }
        }
    }
}
