using BMA.EHR.Domain.Common;
using BMA.EHR.Domain.Extensions;
using BMA.EHR.Domain.Shared;
using BMA.EHR.Application.Repositories.Reports;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Swashbuckle.AspNetCore.Annotations;
using DocumentFormat.OpenXml.Drawing;
using Telerik.Reporting;
using Telerik.Reporting.Processing;
using System.IO;
using BMA.EHR.Application.Repositories;
using BMA.EHR.Report.Service.Requests;
using iTextSharp.text.pdf;
using iTextSharp.text;

namespace BMA.EHR.Report.Service.Controllers
{
    [Route("api/v{version:apiVersion}/report/deceased")]
    [ApiVersion("2.0")]
    [ApiController]
    [Produces("application/json")]
    [Authorize]
    [SwaggerTag("API รายงานบันทึกเวียนแจ้งการถึงแก่กรรม")]
    public class DeceasedReportController : BaseController
    {
        #region " Fields "

        private readonly IWebHostEnvironment _hostingEnvironment;
        private readonly IConfiguration _configuration;
        private readonly GenericReportGenerator _reportGenerator;
        private readonly RetireReportRepository _repository;
        private readonly MinIOService _documentService;
        // for add watermark
        private BaseFont baseFont = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, false);

        #endregion

        #region " Constuctor and Destructor "

        public DeceasedReportController(IWebHostEnvironment hostingEnvironment,
                                        IConfiguration configuration,
                                MinIOService documentService,
                                        GenericReportGenerator reportGenerator,
                                        RetireReportRepository repository)
        {

            _hostingEnvironment = hostingEnvironment;
            _configuration = configuration;
            _reportGenerator = reportGenerator;
            _repository = repository;
            _documentService = documentService;
        }

        #endregion

        #region " Methods "

        #region 36-บันทึกเวียนแจ้งการถึงแก่กรรม
        /// <summary>
        /// 36-บันทึกเวียนแจ้งการถึงแก่กรรม
        /// </summary>
        /// <param name="id">Id รายการบันทึกเวียนแจ้งการถึงแก่กรรม</param>
        /// <param name="exportType">pdf, docx หรือ xlsx</param>
        /// <returns></returns>
        /// <response code="200">เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ</response>
        /// <response code="401">ไม่ได้ Login เข้าระบบ</response>
        /// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
        [HttpGet("36/{exportType}/{id}")]
        public async Task<ActionResult<ResponseObject>> GetDeceasedReportAsync(Guid id, string exportType = "pdf")
        {
            try
            {
                var head = await _repository.GetHeadRetirementDeceasedAsync(id);
                var detail = await _repository.GetRetirementDeceasedAsync(id);
                if (detail != null && head != null)
                {
                    var mergeData = new
                    {
                        Oc = head.GetType().GetProperty("Oc").GetValue(head),
                        Number = head.GetType().GetProperty("Number").GetValue(head),
                        Date = head.GetType().GetProperty("Date").GetValue(head),
                        Subject = head.GetType().GetProperty("Subject").GetValue(head),
                        Send = head.GetType().GetProperty("Send").GetValue(head),
                        FullName = detail.GetType().GetProperty("FullName").GetValue(detail),
                        Position = detail.GetType().GetProperty("Position").GetValue(detail),
                        Reason = detail.GetType().GetProperty("Reason").GetValue(detail),
                        DeceasedDate = detail.GetType().GetProperty("Date").GetValue(detail),
                        CurrentDate = detail.GetType().GetProperty("CurrentDate").GetValue(detail),
                        DeceasedNumber = detail.GetType().GetProperty("Number").GetValue(detail),
                        Location = detail.GetType().GetProperty("Location").GetValue(detail),
                    };
                    var mimeType = "";
                    switch (exportType.Trim().ToLower())
                    {
                        case "pdf": mimeType = "application/pdf"; break;
                        case "docx": mimeType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; break;
                        case "xlsx": mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; break;
                    }

                    //var rptFile = System.IO.Path.Combine(_hostingEnvironment.ContentRootPath, "Reports", $"36-บันทึกเวียนแจ้งการถึงแก่กรรม.trdp");
                    //ReportPackager reportPacker = new ReportPackager();
                    //Telerik.Reporting.Report? report = null;
                    //using (var sourceStream = System.IO.File.OpenRead(rptFile))
                    //{
                    //    report = (Telerik.Reporting.Report)reportPacker.UnpackageDocument(sourceStream);
                    //}
                    //report.DataSource = mergeData;
                    //System.Collections.Hashtable deviceInfo = new System.Collections.Hashtable();
                    //InstanceReportSource instanceReportSource = new InstanceReportSource()
                    //{
                    //    ReportDocument = report,
                    //};
                    //ReportProcessor reportProcessor = new ReportProcessor(_configuration);
                    //RenderingResult result = reportProcessor.RenderReport($"{exportType}", instanceReportSource, deviceInfo);
                    //return File(result.DocumentBytes, mimeType, $"รายละเอียดบันทึกเวียนแจ้งการถึงแก่กรรม.{exportType.Trim().ToLower()}");
                    var data = new
                    {
                        template = "deceased",
                        reportName = "docx-report",
                        data = mergeData
                    };
                    return Success(data);
                }
                else
                {
                    return NotFound();
                }
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 36-บันทึกเวียนแจ้งการถึงแก่กรรม
        /// </summary>
        /// <param name="id">Id รายการบันทึกเวียนแจ้งการถึงแก่กรรม</param>
        /// <returns></returns>
        /// <response code="200">เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ</response>
        /// <response code="401">ไม่ได้ Login เข้าระบบ</response>
        /// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
        [HttpGet("copy/36/{id}")]
        [AllowAnonymous]
        public async Task<ActionResult<ResponseObject>> GetDeceasedReportCopyAsync(Guid id)
        {
            try
            {
                var head = await _repository.GetHeadRetirementDeceasedAsync(id);
                var data = await _repository.GetRetirementDeceasedAsync(id);
                if (data != null || head != null)
                {
                    var mergeData = new
                    {
                        Oc = head.GetType().GetProperty("Oc").GetValue(head),
                        Number = head.GetType().GetProperty("Number").GetValue(head),
                        Date = head.GetType().GetProperty("Date").GetValue(head),
                        Subject = head.GetType().GetProperty("Subject").GetValue(head),
                        Send = head.GetType().GetProperty("Send").GetValue(head),
                        FullName = data.GetType().GetProperty("FullName").GetValue(data),
                        Position = data.GetType().GetProperty("Position").GetValue(data),
                        Reason = data.GetType().GetProperty("Reason").GetValue(data),
                        DeceasedDate = data.GetType().GetProperty("Date").GetValue(data),
                        CurrentDate = data.GetType().GetProperty("CurrentDate").GetValue(data),
                        DeceasedNumber = data.GetType().GetProperty("Number").GetValue(data),
                        Location = data.GetType().GetProperty("Location").GetValue(data),
                    };
                    // var mimeType = "";
                    // switch (exportType.Trim().ToLower())
                    // {
                    //     case "pdf": mimeType = "application/pdf"; break;
                    //     case "docx": mimeType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; break;
                    //     case "xlsx": mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; break;
                    // }

                    var rptFile = System.IO.Path.Combine(_hostingEnvironment.ContentRootPath, "Reports", $"36-บันทึกเวียนแจ้งการถึงแก่กรรม.trdp");
                    ReportPackager reportPacker = new ReportPackager();
                    Telerik.Reporting.Report? report = null;
                    using (var sourceStream = System.IO.File.OpenRead(rptFile))
                    {
                        report = (Telerik.Reporting.Report)reportPacker.UnpackageDocument(sourceStream);
                    }
                    report.DataSource = mergeData;
                    System.Collections.Hashtable deviceInfo = new System.Collections.Hashtable();
                    InstanceReportSource instanceReportSource = new InstanceReportSource()
                    {
                        ReportDocument = report,
                    };
                    ReportProcessor reportProcessor = new ReportProcessor(_configuration);
                    RenderingResult result = reportProcessor.RenderReport($"pdf", instanceReportSource, deviceInfo);
                    // return File(result.DocumentBytes, mimeType, $"รายละเอียดบันทึกเวียนแจ้งการถึงแก่กรรม.{exportType.Trim().ToLower()}");

                    var now = DateTime.Now.ToString("yyyyMMdd-HHmmss");
                    var file = System.IO.Path.Combine(_hostingEnvironment.WebRootPath, "tmp", $"tmp-{now}.pdf");
                    var file_copy = System.IO.Path.Combine(_hostingEnvironment.WebRootPath, "tmp", $"tmp-{now}-copy.pdf");

                    try
                    {
                        // Copy to File
                        System.IO.File.WriteAllBytes(file, result.DocumentBytes);
                        var watermark_text = "COPY COPY COPY COPY";
                        var fName = $"รายละเอียดบันทึกเวียนแจ้งการถึงแก่กรรม.pdf";

                        AddWatermark(file, file_copy, watermark_text);

                        using (var fileStream = new System.IO.FileStream(file_copy, FileMode.Open, FileAccess.Read))
                        {
                            using (var ms = new MemoryStream())
                            {
                                fileStream.CopyTo(ms);
                                ms.Flush();
                                return File(ms.ToArray(), "application/octet-stream", fName);
                            }
                        }
                    }
                    catch
                    {
                        throw;
                    }
                    finally
                    {
                        if (System.IO.File.Exists(file))
                            System.IO.File.Delete(file);

                        if (System.IO.File.Exists(file_copy))
                            System.IO.File.Delete(file_copy);
                    }
                }
                else
                {
                    return NotFound();
                }
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// อัปไฟล์บันทึกเวียนแจ้งการถึงแก่กรรม
        /// </summary>
        /// <param name="id">id </param>
        /// <returns></returns>
        /// <response code="200">เมื่อทำการอ่านข้อมูลจาก Relational Database สำเร็จ</response>
        /// <response code="401">ไม่ได้ Login เข้าระบบ</response>
        /// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
        [HttpPut("attachment/36/{id}")]
        public async Task<ActionResult<ResponseObject>> UploadDeceasedReportAsync([FromForm] FileRequest req, Guid id)
        {
            try
            {
                var data = await _repository.GetRetirementDeceasedAsync(id);
                if (data == null)
                    return NotFound();
                // check upload file
                if (Request.Form.Files == null || Request.Form.Files.Count == 0)
                {
                    return Error(GlobalMessages.NoFileToUpload);
                }
                var file = Request.Form.Files[0];
                var cover = await _documentService.UploadFileAsync(file);
                await _repository.UploadFileRetirementDeceasedAsync(id, cover);
                return Success();
            }
            catch
            {
                throw;
            }
        }
        #endregion

        #endregion

        #region " Add Watermark "

        private void AddWaterMarkText(PdfContentByte pdfData, string watermarkText, BaseFont font, float fontSize, float angle, BaseColor color, iTextSharp.text.Rectangle realPageSize)
        {
            var gstate = new PdfGState { FillOpacity = 0.5f, StrokeOpacity = 0.3f };
            pdfData.SaveState();
            pdfData.SetGState(gstate);
            pdfData.SetColorFill(color);
            pdfData.BeginText();
            pdfData.SetFontAndSize(font, fontSize);
            var x = (realPageSize.Right + realPageSize.Left) / 2;
            var y = (realPageSize.Bottom + realPageSize.Top) / 2;
            pdfData.ShowTextAligned(Element.ALIGN_CENTER, watermarkText, x, y, angle);
            pdfData.EndText();
            pdfData.RestoreState();
        }

        private bool AddWatermark(string inputfilepath, string outputfilepath, string watermark_text)
        {
            PdfReader pdfReader = null;
            PdfStamper pdfStamper = null;
            try
            {

                pdfReader = new PdfReader(inputfilepath);
                int numberOfPages = pdfReader.NumberOfPages;
                iTextSharp.text.Rectangle pagesize = pdfReader.GetPageSize(1);
                pdfStamper = new PdfStamper(pdfReader, new FileStream(outputfilepath, FileMode.Create));

                for (int i = 1; i <= numberOfPages; i++)
                {
                    var dc = pdfStamper.GetOverContent(i);
                    AddWaterMarkText(dc, watermark_text, baseFont, 30, 45, BaseColor.DARK_GRAY, pdfReader.GetPageSizeWithRotation(i));
                }
                return true;
            }
            catch (Exception ex)
            {
                ex.Message.Trim();
                return false;
            }
            finally
            {
                if (pdfStamper != null)
                    pdfStamper.Close();

                if (pdfReader != null)
                    pdfReader.Close();
            }
        }

        #endregion
    }
}
