using Asp.Versioning;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using OnlineSalesAutoCrop.CoreAPI;
using OnlineSalesAutoCrop.CoreAPI.Models.Requests.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Models.Responses.Integrations;
using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Integrations;
using System;
using System.Threading.Tasks;

namespace OnlineSalesAutoCrop.CoreAPI.Controllers
{
    /// <summary>
	/// 
	/// </summary>
	/// <remarks>
	/// 
	/// </remarks>
	/// <param name="logger"></param>
	/// <param name="integrationService"></param>
	[Authorize]
    [ApiController]
    [ApiVersion("1.0")]
    [ValidateAntiForgeryToken]
    [Route("api/v{version:apiVersion}/Integration")]
    public class IntegrationController(ILogger<IntegrationAuthController> logger, IIntegrationService integrationService) : ControllerBase
    {

        private readonly ILogger _logger = logger;
        private readonly IIntegrationService _integrationService = integrationService;


        /// <summary>
        /// Insert or Update Customers for SAP 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <returns>if created return 201 or if updated return 200 true</returns>
        [HttpPost("Customers")]
        [IgnoreAntiforgeryToken]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IntegrationLoginResponse))]
        public async Task<IActionResult> UpsertCustomers(IntegrationCustomerRequest request)
        {
            IntegrationCustomerResponse response = new IntegrationCustomerResponse();
            try
            {
                response = await _integrationService.UpsertCustomerAsync(request);
                if (!response.IsUpdated)
                {
                    response.ReturnMessage.Add($"Customer Created Successfully for CustomerNumber :{request.CustomerNumber} & CompanyCode:{request.CompanyCode}");
                    response.ReturnStatus = StatusCodes.Status201Created;
                    return StatusCode(StatusCodes.Status201Created, response);
                }
                else
                {
                    response.ReturnMessage.Add($"Customer Updated Successfully for CustomerNumber :{request.CustomerNumber} & CompanyCode:{request.CompanyCode}");
                    response.ReturnStatus = StatusCodes.Status200OK;
                    return StatusCode(StatusCodes.Status200OK, response);
                }
            }
            catch (Exception ex)
            {
                string msg = $"Exception Occur in Customer Operation {request?.CustomerName}~{request?.CompanyCode}";
                _logger.LogError(exception: ex,  msg);
                response.ReturnStatus = StatusCodes.Status500InternalServerError;
                response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
                return StatusCode(StatusCodes.Status500InternalServerError, response);
            }
        }

        /// <summary>
        /// Insert or Update Employees for SAP 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <returns>if created return 201 or if updated return 200 true</returns>
        [HttpPost("Employees")]
        [IgnoreAntiforgeryToken]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(EmployeeIntegrationReqResponse))]
        public async Task<IActionResult> UpsertEmployee(IntegrationEmployeeRequest request)
        {
            EmployeeIntegrationReqResponse response = new EmployeeIntegrationReqResponse();
            try
            {
                response = await _integrationService.UpsertEmployeeAsync(request);
                if (!response.IsUpdated)
                {
                    response.ReturnMessage.Add($"Employee Created Successfully for EmployeeVendorName :{request.EmployeeVendorName} & SalesOrgCode:{request.CompanyCode}");
                    response.ReturnStatus = StatusCodes.Status201Created;
                    return StatusCode(StatusCodes.Status201Created, response);
                }
                else
                {
                    response.ReturnMessage.Add($"Employee Updated Successfully for EmployeeVendorName :{request.EmployeeVendorName} & SalesOrgCode:{request.CompanyCode}");
                    response.ReturnStatus = StatusCodes.Status200OK;
                    return StatusCode(StatusCodes.Status200OK, response);
                }
            }
            catch (Exception ex)
            {
                string msg = $"Exception Occur in Employee Operation {request?.EmployeeVendorName}~{request?.CompanyCode}";
                _logger.LogError(exception: ex, msg);
                response.ReturnStatus = StatusCodes.Status500InternalServerError;
                response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
                return StatusCode(StatusCodes.Status500InternalServerError, response);
            }
        }


        /// <summary>
        /// Insert or Update Material for SAP 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <returns>if created return 201 or if updated return 200 true</returns>
        [HttpPost("Materials")]
        [IgnoreAntiforgeryToken]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(MaterialIntegrationReqResponse))]
        [ProducesResponseType(StatusCodes.Status201Created, Type = typeof(MaterialIntegrationReqResponse))]
        public async Task<IActionResult> UpsertMeterial(IntegrationMaterialRequest request)
        {
            MaterialIntegrationReqResponse response = new MaterialIntegrationReqResponse();
            try
            {
                response = await _integrationService.UpsertMaterialAsync(request);
                if (!response.IsUpdated)
                {
                    response.ReturnMessage.Add($"Material Created Successfully for MaterialCode :{request.MaterialCode} ");
                    response.ReturnStatus = StatusCodes.Status201Created;
                    return StatusCode(StatusCodes.Status201Created, response);
                }
                else
                {
                    response.ReturnMessage.Add($"Material Updated Successfully for MaterialCode :{request.MaterialCode} ");
                    response.ReturnStatus = StatusCodes.Status200OK;
                    return StatusCode(StatusCodes.Status200OK, response);
                }
            }
            catch (Exception ex)
            { 
                string msg = $"Exception Occur in Material Operation {request?.MaterialCode}";
                _logger.LogError(exception: ex, msg);
                response.ReturnStatus = StatusCodes.Status500InternalServerError;
                response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
                return StatusCode(StatusCodes.Status500InternalServerError, response);
            }
        }

        /// <summary>
        /// Insert or Update Material Prices for SAP 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <returns>if created return 201 or if updated return 200 true</returns>
        [HttpPost("MaterialPrices")]
        [IgnoreAntiforgeryToken]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(MaterialIntegrationPriceReqResponse))]
        [ProducesResponseType(StatusCodes.Status201Created, Type = typeof(MaterialIntegrationPriceReqResponse))]
        public async Task<IActionResult> UpsertMeterialPrices(IntegrationMaterialPriceRequest request)
        {
            MaterialIntegrationPriceReqResponse response = new MaterialIntegrationPriceReqResponse();
            try
            {
                response = await _integrationService.UpsertMaterialPriceAsync(request);
                if (!response.IsUpdated)
                {
                    response.ReturnMessage.Add($"Material Price Created Successfully for MaterialCode :{request.MaterialCode} And ConditionType : {request.ConditionType}" +
                        $"And Customer Number : {request.CustomerNumber} And Customer Group Code : {request.CustomerGroupCode} ");
                    response.ReturnStatus = StatusCodes.Status201Created;
                    return StatusCode(StatusCodes.Status201Created, response);
                }
                else
                {
                    response.ReturnMessage.Add($"Material Price Updated Successfully for MaterialCode :{request.MaterialCode} And ConditionType : {request.ConditionType}" +
                        $"And Customer Number : {request.CustomerNumber} And Customer Group Code : {request.CustomerGroupCode} "); 
                    response.ReturnStatus = StatusCodes.Status200OK;
                    return StatusCode(StatusCodes.Status200OK, response);
                }
            }
            catch (Exception ex)
            {
                string msg = $"Exception Occur in Material Price Operation MaterialCode :{request.MaterialCode} And ConditionType : {request.ConditionType}" +
                        $"And Customer Number : {request.CustomerNumber} And Customer Group Code : {request.CustomerGroupCode} ";
                _logger.LogError(exception: ex, msg);
                response.ReturnStatus = StatusCodes.Status500InternalServerError;
                response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
                return StatusCode(StatusCodes.Status500InternalServerError, response);
            }
        }

        /// <summary>
        /// Insert or Update Material Prices for SAP 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <returns>if created return 201 or if updated return 200 true</returns>
        [HttpPost("MaterialFreeGoods")]
        [IgnoreAntiforgeryToken]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(MaterialFreeGoodsByReqResponse))]
        [ProducesResponseType(StatusCodes.Status201Created, Type = typeof(MaterialFreeGoodsByReqResponse))]
        public async Task<IActionResult> UpsertMaterialFreeGoods(IntegrationMaterialFreeGoodsRequest request)
        {
            MaterialFreeGoodsByReqResponse response = new MaterialFreeGoodsByReqResponse();
            try
            {
                response = await _integrationService.UpsertMaterialFreeGoodsAsync(request);
                if (!response.IsUpdated)
                {
                    response.ReturnMessage.Add($"Material Free Goods Created Successfully for SalesOrg :{request.SalesOrg} " +
                        $"And CustomerPriceGroup : {request.CustomerPriceGroup} And MaterialCode : {request.MaterialCode} And DistributorChannel : {request.DistributionChannel}" +
                        $" And Customer Number :{request.CustomerNumber} And Customer Price Group : {request.CustomerPriceGroup}");
                    response.ReturnStatus = StatusCodes.Status201Created;
                    return StatusCode(StatusCodes.Status201Created, response);
                }
                else
                {
                    response.ReturnMessage.Add($"Material Free Goods Updated Successfully for SalesOrg :{request.SalesOrg} " +
                        $"And CustomerPriceGroup : {request.CustomerPriceGroup} And MaterialCode : {request.MaterialCode} And DistributorChannel : {request.DistributionChannel}" +
                        $" And Customer Number :{request.CustomerNumber} And Customer Price Group : {request.CustomerPriceGroup}");
                    response.ReturnStatus = StatusCodes.Status200OK;
                    return StatusCode(StatusCodes.Status200OK, response);
                }
            }
            catch (Exception ex)
            {
                string msg = $"Exception Occur in Material Free Goods Operation SalesOrg :{request.SalesOrg} " +
                        $" And CustomerPriceGroup : {request.CustomerPriceGroup} And MaterialCode : {request.MaterialCode} And DistributorChannel : {request.DistributionChannel}" +
                        $" And Customer Number :{request.CustomerNumber} And Customer Price Group : {request.CustomerPriceGroup}";
                _logger.LogError(exception: ex, msg);
                response.ReturnStatus = StatusCodes.Status500InternalServerError;
                response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
                return StatusCode(StatusCodes.Status500InternalServerError, response);
            }
        }

        /// <summary>
        /// Insert or Update Payment Terms for SAP 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <returns>if created return 201 or if updated return 200 true</returns>
        [HttpPost("PaymentTerms")]
        [IgnoreAntiforgeryToken]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IntegrationPaymentTermReqResponse))]
        [ProducesResponseType(StatusCodes.Status201Created, Type = typeof(IntegrationPaymentTermReqResponse))]
        public async Task<IActionResult> UpsertPaymentTerms(IntegrationPaymentTermRequest request)
        {
            IntegrationPaymentTermReqResponse response = new IntegrationPaymentTermReqResponse();
            try
            {
                response = await _integrationService.UpsertPaymentTermsAsync(request);
                if (!response.IsUpdated)
                {
                    response.ReturnMessage.Add($"Payment Terms Created Successfully for SalesOrg :{request.SalesOrg} " +
                        $"And CreditCode : {request.CreditCode} ");
                    response.ReturnStatus = StatusCodes.Status201Created;
                    return StatusCode(StatusCodes.Status201Created, response);
                }
                else
                {
                    response.ReturnMessage.Add($"Payment Terms Updated Successfully for SalesOrg :{request.SalesOrg} " +
                        $"And CreditCode : {request.CreditCode} ");
                    response.ReturnStatus = StatusCodes.Status200OK;
                    return StatusCode(StatusCodes.Status200OK, response);
                }
            }
            catch (Exception ex)
            {
                string msg = $"Exception Occur in Payment Terms for SalesOrg :{request.SalesOrg} " +
                        $"And CreditCode : {request.CreditCode} ";
                _logger.LogError(exception: ex, msg);
                response.ReturnStatus = StatusCodes.Status500InternalServerError;
                response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
                return StatusCode(StatusCodes.Status500InternalServerError, response);
            }
        }

        /// <summary>
        /// Insert Invoices for SAP 
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <param name="request"></param>
        /// <returns>if created return 201 or if updated return 200 true</returns>
        [HttpPost("Invoices")]
        [IgnoreAntiforgeryToken]
        [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IntegrationInvoiceReqResponse))]
        [ProducesResponseType(StatusCodes.Status201Created, Type = typeof(IntegrationInvoiceReqResponse))]
        public async Task<IActionResult> SaveInvoices(IntegrationInvoiceRequest request)
        {
            IntegrationInvoiceReqResponse response = new IntegrationInvoiceReqResponse();
            try
            {
                response = await _integrationService.SaveInvoiceAsync(request);
                response.ReturnMessage.Add($"Successfully Save the Invoices for InvoiceNo :{request.InvoiceDocumentNo} " +
                        $"And InvoiceDate : {request.InvoiceDate} ");
                response.ReturnStatus = StatusCodes.Status201Created;
                return StatusCode(StatusCodes.Status201Created, response);
            }
            catch (Exception ex)
            {
                string msg = $"Exception Occur in Invoices for InvoiceNo :{request.InvoiceDocumentNo} " +
                        $"And InvoiceDate : {request.InvoiceDate} " ;
                _logger.LogError(exception: ex, msg);
                response.ReturnStatus = StatusCodes.Status500InternalServerError;
                response.ReturnMessage.Add(ex.InnerException != null ? ex.InnerException.Message : ex.Message);
                return StatusCode(StatusCodes.Status500InternalServerError, response);
            }
        }
    }
}