using System;
using System.Linq;
using System.Web.Mvc;
using Platnosci.Models;
using Platnosci.Core.Linq;
using Platnosci.Core.Interface;
using System.Configuration;
using System.Net;
using System.IO;
using System.Threading;

namespace Platnosci.Controllers
{
    [Authorize]
    public class MerchantController : Controller
    {
        public const string BAD_HASH = "zlyHash";       //błędne hasło - odpowied z eCard
        public const string CARDS = "CARDS";            //obsługa tylko kart płatniczych
        public const string KOD_POLSKA = "616";         //kod kraju Akceptanta - Polska
        public const string KODOWANIE = "ISO-8859-2";
        public const string HASH_ERROR_INFO = "payment not exist";

        private readonly IRepository<vPlatnosciEcard> _repVPayment;
        private readonly IRepository<PlatnosciEcard> _repPayment; 
        private readonly FunkcjePlatnosci _funkcjePlatnosci;
        private readonly ITranslateManager _translateManager;

        public MerchantController()
        {
            _repVPayment = new Repository<vPlatnosciEcard>(new DataContext());
            _repPayment = new Repository<PlatnosciEcard>(new DataContext());
            _funkcjePlatnosci = new FunkcjePlatnosci();
            _translateManager = new Translation();
        }

        public ActionResult Merchant(Payer payer, string language)
        {
            System.Diagnostics.Debug.WriteLine("MerchantController:Merchant:" + language);
            language = _funkcjePlatnosci.setLanguage(language);

            var id1 = Convert.ToInt32(payer.Id_faktury);
            var platnosc = _repVPayment.Find(p => p.ID_faktury == id1).SingleOrDefault();
                 
            if (platnosc == null) 
                return View("Error1", IsError("brakdanych", 0));
            
            if (!_funkcjePlatnosci.UserIdentity(platnosc, ControllerContext.HttpContext.User.Identity.Name))
                return View("Error1", IsError("weryfikacja", 0));           

            var waluta = _funkcjePlatnosci.setAmount(platnosc);
            var newPayment = InitNewPayment(id1, platnosc, waluta, payer );            

            var systemKs = platnosc.SystemKsiegowyId.ToString();
            if (ConfigurationManager.AppSettings["wersja"] == "TEST")
                systemKs = "2";

            var createPayment = AddNewPayment(newPayment);
            
            if (createPayment == false)
                return View("Error1", IsError("error_hash", payer.Id_faktury));

            var merchant = getMerchantInfo(systemKs);
           
            var hash = GetHash(newPayment, merchant);
            hash = hash.Replace("\n","");
          
            if (hash == BAD_HASH || hash == "" || hash == HASH_ERROR_INFO)
                return View("Error1", IsError("error_hash", payer.Id_faktury));

            //przeslanie w linku ordernumber potrzebnego do wyswietlenia potwierdzenia
            var orderek = _repPayment.GetOrdernumber(newPayment.ORDERDESCRIPTION, newPayment.IDFaktury, newPayment.Data);

            var linkFail = ConfigurationManager.AppSettings["Strona"];
            linkFail += "/" + language + ConfigurationManager.AppSettings["LinkFail"];
            linkFail += "/" + newPayment.IDFaktury + "?o=" + orderek;

            var linkOk = ConfigurationManager.AppSettings["Strona"];
            linkOk += "/" + language + ConfigurationManager.AppSettings["LinkOk"];
            linkOk += "/" + newPayment.IDFaktury + "?o=" + orderek;

            if (merchant != null && !String.IsNullOrEmpty(merchant.Id))
                SendRequest(newPayment, hash, merchant, linkFail, linkOk);
            else 
                return View("Error1", IsError("error_hash", payer.Id_faktury));

            return new EmptyResult();          
        }        
        private PlatnosciEcard InitNewPayment(int id, vPlatnosciEcard platnosc, Waluta waluta, Payer payer)
        {
            var newPayment = new PlatnosciEcard();
            newPayment.IDFaktury = id;
            newPayment.ORDERDESCRIPTION = platnosc.Faktura_Numer;
            newPayment.nip = platnosc.nip;
            newPayment.nrZlecenia = "";
            newPayment.AMOUNT = waluta.Amount;
            newPayment.CURRENCY = waluta.Currency;
            newPayment.SESSIONID = Session.SessionID;
            newPayment.NAME = payer.FirstName;
            newPayment.SURNAME = payer.LastName;
            newPayment.AUTODEPOSIT = true;
            newPayment.LANGUAGE = Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName.ToUpper(); 
            newPayment.CHARSET = KODOWANIE;
            newPayment.COUNTRY = KOD_POLSKA;
            newPayment.JS = true;
            newPayment.PAYMENTTYPE = CARDS;
            newPayment.Data = DateTime.Now;
            newPayment.Status = null;
            newPayment.Status_data = null;
            return newPayment;
        }
        
        private bool AddNewPayment(PlatnosciEcard platnosc)
        {
            if (platnosc != null)
            {                
                _repPayment.Insert(platnosc);
                return true;
            }
            return false;
        }

        private string GetHash(PlatnosciEcard p, Merchant merchant)
        {
            var platnosc = _repPayment.Find(i => i.ORDERDESCRIPTION == p.ORDERDESCRIPTION && i.IDFaktury == p.IDFaktury && i.Data == p.Data).First();

            if (platnosc == null || merchant == null) return HASH_ERROR_INFO;

            var adres = "https://pay.ecard.pl/servlet/HS?orderNumber=" + platnosc.ORDERNUMBER;
            var req = (HttpWebRequest)WebRequest.Create(adres);
            var dane = "&orderDescription=&amount=" + platnosc.AMOUNT;
            dane += "&currency=" + platnosc.CURRENCY;
            dane += string.Format("&merchantId={0}&password={1}", merchant.Id, merchant.Password);

            var bdata = System.Text.Encoding.ASCII.GetBytes(dane);
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";
            req.ContentLength = dane.Length;

            var reqStream = req.GetRequestStream();
            reqStream.Write(bdata, 0, bdata.Length);
            reqStream.Close();

            var streamResponse = new StreamReader(req.GetResponse().GetResponseStream());
            string strResponse = streamResponse.ReadToEnd();
            streamResponse.Close();
                     
            return strResponse;
        }

        private void SendRequest(PlatnosciEcard m, string hash, Merchant merchant, string linkok, string linkfail)
        {
            var adres = ConfigurationManager.AppSettings["eCard.Url"] + "?ORDERDESCRIPTION=" + m.ORDERDESCRIPTION;

            var dane = "&AMOUNT=" + m.AMOUNT + "&CURRENCY=" + m.CURRENCY + "&ORDERNUMBER=" + m.ORDERNUMBER;
            dane += "&NAME=" + m.NAME + "&SURNAME=" + m.SURNAME + "&LANGUAGE=" + m.LANGUAGE + "&CHARSET=ISO-8859-2";
            dane += "&COUNTRY=616&PAYMENTTYPE=CARDS&JS=1&HASH=" + hash + "&MERCHANTID=" + merchant.Id + "&AUTODEPOSIT=" + m.AUTODEPOSIT;
            dane += "&LINKFAIL=" + linkfail + "&LINKOK=" + linkok + "&SESSIONID=" + m.SESSIONID;
            Response.Redirect(adres + dane);
        }
        public ErrorViewData IsError(string errortxt, int idFaktury)
        {
            if (errortxt == "brakdanych")
                errortxt = _translateManager.Translate("tlumaczenia", "brakdanych");
            else if (errortxt == "weryfikacja")
                errortxt = _translateManager.Translate("tlumaczenia", "weryfikacja");
            else if (errortxt == "error_hash")
                errortxt = _translateManager.Translate("tlumaczenia", "error_hash");

            return _funkcjePlatnosci.InitErrorViewData(errortxt, idFaktury);
        }
        public Merchant getMerchantInfo( string systemKs)
        {
            var merchant = new Merchant();
            if (systemKs == "2")
            {
                merchant.Id = "171485000";
                merchant.Password = "ashSeth2";
            }
            else
            {
                merchant.Id = "170906000";
                merchant.Password = "JaYpqfs0";
            }              
            return merchant;
        }
    }
}
