using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Linq;

namespace OI.Metrology.Archive.ApiControllers;

using OI.Metrology.Archive.Models;
using OI.Metrology.Shared.DataModels;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Services;
using System.Collections.Generic;
using System.Text.Json;

// using System.Data.Common;

public class ToolTypesController : Controller
{
    // this controller powers the bulk of the UI
    // it is named after the /api/tooltypes prefix
    // the URL pattern is RESTful and the tool type is the root of every request

    private readonly AppSettings _AppSettings;
    private readonly IAttachmentsService _AttachmentsService;
    private readonly IMetrologyRepository _MetrologyRepository;

    public ToolTypesController(AppSettings appSettings, IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService)
    {
        _AppSettings = appSettings;
        _AttachmentsService = attachmentsService;
        _MetrologyRepository = metrologyRepository;
    }

    // Get a list of tooltypes, returns just Name and ID
    [HttpGet("/api/tooltypes")]
    public IActionResult Index()
    {
        var r = new
        {
            Results = _MetrologyRepository.GetToolTypes().Select(tt => new { tt.ToolTypeName, tt.ID })
        };
        return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
    }

    // Gets the metadata for a tooltype, accepts a parameter which sorts the results
    // This is used to setup the grid displays on the UI
    [HttpGet("/api/tooltypes/{id}")]
    public IActionResult GetToolTypeMetadata(int id, string sortby = "")
    {
        ToolType tt = _MetrologyRepository.GetToolTypeByID(id);
        IEnumerable<ToolTypeMetadata> md = _MetrologyRepository.GetToolTypeMetadataByToolTypeID(id);

        if (string.Equals(sortby, "grid", StringComparison.OrdinalIgnoreCase))
            md = md.OrderBy(f => f.GridDisplayOrder).ToList();
        if (string.Equals(sortby, "table", StringComparison.OrdinalIgnoreCase))
            md = md.OrderBy(f => f.GridDisplayOrder).ToList();

        var r = new
        {
            Results = new
            {
                ToolType = tt,
                Metadata = md
            }
        };
        return Json(r, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true });
    }
    // Just Changed here
    // Gets headers, request/response format is to allow paging with igniteUI
    // The headerid parameter is used for navigating directly to a header, when the button is clicked in Awaiting Dispo
    [HttpGet("/api/tooltypes/{id}/headers")]
    public IActionResult GetHeaders(
        int id,
        [FromQuery] DateTime? datebegin,
        [FromQuery] DateTime? dateend,
        [FromQuery] int? page,
        [FromQuery] int? pagesize,
        [FromQuery] long? headerid)
    {
        long totalRecs;

        System.Data.DataTable dt = _MetrologyRepository.GetHeaders(id, datebegin, dateend, page, pagesize, headerid, out totalRecs);

        var r = new
        {
            Results = dt,
            TotalRows = totalRecs,
        };
        string json = JsonConvert.SerializeObject(r);

        return Content(json);
    }

    // Gets header titles, used in the Run Headers UI
    [HttpGet("/api/tooltypes/{id}/headertitles")]
    public IActionResult GetHeaderTitles(
        int id,
        [FromQuery] int? page,
        [FromQuery] int? pagesize)
    {
        long totalRecs;

        IEnumerable<HeaderCommon> dt = _MetrologyRepository.GetHeaderTitles(id, page, pagesize, out totalRecs);

        var r = new
        {
            Results = dt,
            TotalRows = totalRecs,
        };
        string json = JsonConvert.SerializeObject(r);

        return Content(json);
    }

    // Get all of the fields for a header, used with the Run Header UI
    [HttpGet("/api/tooltypes/{id}/headers/{headerid}/fields")]
    public IActionResult GetHeaderFields(
        int id,
        long headerid)
    {
        var r = new
        {
            Results = _MetrologyRepository.GetHeaderFields(id, headerid).Select(x => new { Column = x.Key, x.Value }).ToList()
        };
        string json = JsonConvert.SerializeObject(r);

        return Content(json);
    }

    // Get the data for a header, used with the Run Info UI
    [HttpGet("/api/tooltypes/{id}/headers/{title}/data/isSharePoint")]
    public IActionResult GetData(
        int id,
        string title)
    {

        var r = new
        {
            Results = _MetrologyRepository.GetDataSharePoint(id, title)
        };
        string json = JsonConvert.SerializeObject(r);

        return Content(json);
    }
    // Get the data for a header, used with the Run Info UI
    [HttpGet("/api/tooltypes/{id}/headers/{headerid}/data")]
    public IActionResult GetData(
        int id,
        long headerid)
    {

        var r = new
        {
            Results = _MetrologyRepository.GetData(id, headerid)
        };
        string json = JsonConvert.SerializeObject(r);

        return Content(json);
    }

    // Display an attachment, used for Run Info - note it is by tool type ID and attachment GUID, so it is best for internal use
    [HttpGet("/api/tooltypes/{toolTypeId}/{tabletype}/files/{attachmentId}/{filename}")]
    public IActionResult GetAttachment(
        int toolTypeId,
        string tabletype,
        string attachmentId,
        string filename)
    {

        ToolType tt = _MetrologyRepository.GetToolTypeByID(toolTypeId);

        bool header = !string.Equals(tabletype.Trim(), "data", StringComparison.OrdinalIgnoreCase);

        Guid attachmentIdParsed;
        if (!Guid.TryParse(attachmentId, out attachmentIdParsed))
            return Content("Invalid attachment id");

        // figure out what content type to use.  this is very simple because there are only two types being used
        string contenttype = "application/pdf";
        if (filename.ToLower().TrimEnd().EndsWith(".txt"))
            contenttype = "text/plain";

        // Get attachment stream and feed it to the client
        Stream fs = _AttachmentsService.GetAttachmentStreamByAttachmentId(tt, header, attachmentIdParsed, filename);
        return File(fs, contenttype);
    }

    // This endpoint triggers writing of the OI Export file       
    [HttpPost("/api/tooltypes/{toolTypeId}/headers/{headerid}/oiexport")]
    public IActionResult OIExport(int toolTypeId, long headerid)
    {
        // Call the export stored procedure
        System.Data.DataSet ds = _MetrologyRepository.GetOIExportData(toolTypeId, headerid);

        try
        {
            // The SP must return 3 result tables
            if (ds.Tables.Count != 3)
                throw new Exception("Error exporting, invalid results");

            // The first table has just one row, which is the export filename
            if (ds.Tables[0].Rows.Count != 1)
                throw new Exception("Error exporting, invalid filename");

            string? filename = Convert.ToString(ds.Tables[0].Rows[0][0]);

            // The second table has the header data
            if (ds.Tables[1].Rows.Count != 1)
                throw new Exception("Error exporting, invalid header data");

            System.Text.StringBuilder sb = new();

            foreach (object? o in ds.Tables[1].Rows[0].ItemArray)
            {
                if ((o is not null) && (!Convert.IsDBNull(o)))
                    _ = sb.Append(Convert.ToString(o));
                _ = sb.Append('\t');
            }

            // The third table has the detail data
            foreach (System.Data.DataRow dr in ds.Tables[2].Rows)
            {
                foreach (object? o in dr.ItemArray)
                {
                    if ((o is not null) && (!Convert.IsDBNull(o)))
                        _ = sb.Append(Convert.ToString(o));
                    _ = sb.Append('\t');
                }
            }
            _ = sb.AppendLine();

            // The output file will only have one line, the header columns are output first
            // Then each detail rows has it's columns appended
            // H1, H2, H3, D1.1, D1.2, D1.3, D2.1, D2.2, D2.3, etc
            // Write the file
            System.IO.File.WriteAllText(
                Path.Join(_AppSettings.OIExportPath, filename),
                sb.ToString());

        }
        catch (Exception ex)
        {
            string json = JsonConvert.SerializeObject(new
            {
                ex.Message,
            });
            return BadRequest(json);
        }

        var r = new
        {
            Message = "OK",
        };
        return Ok(r);
    }

}