using System;
using System.Linq;
using System.Net;
using System.Xml;
using System.Xml.Linq;
using bahnplan.web.database;
using bahnplan.web.database.Tables;
using bahnplan.web.JSON;
using LinqToDB;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Newtonsoft.Json;
using Leg = bahnplan.web.database.Tables.Leg;

namespace bahnplan.web.Pages {
	public class TicketModel : PageModel {
		public int TripId;

		public void OnGet() {
			if (HttpContext.Session.GetString("authorized") != "true")
				return;

			using var db = new Database.DbConn();
			if (!string.IsNullOrWhiteSpace(Request.Query["tripid"].ToString()))
				if (db.Trips.First(p => p.TripId == int.Parse(Request.Query["tripid"].ToString())).UserId != int.Parse(HttpContext.Session.GetString("uid")))
					return;

			if (db.Tickets.Any(p => p.OrderId == Request.Query["order"].ToString())) {
				var tripId = Request.Query["action"] == "addleg"
					? int.Parse(Request.Query["tripid"])
					: db.InsertWithInt32Identity(new Trip {UserId = int.Parse(HttpContext.Session.GetString("uid"))});
				var ticketId = db.Tickets.First(p => p.OrderId == Request.Query["order"].ToString()).TicketId;
				var ticketId2 = db.Tickets.FirstOrDefault(p => p.OrderId == Request.Query["order"].ToString() + "_2")?.TicketId;

				foreach (var leg in db.TicketLegs.Where(p => p.TicketId == ticketId).ToList())
					db.InsertWithInt32Identity(new Leg {
						TripId       = tripId,
						UserId       = int.Parse(HttpContext.Session.GetString("uid")),
						TrainType    = leg.TrainType,
						TrainNr      = leg.TrainNr,
						ArrStation   = leg.ArrStation,
						ArrStationId = leg.ArrStationId,
						ArrTime      = leg.ArrTime,
						DepStation   = leg.DepStation,
						DepStationId = leg.DepStationId,
						DepTime      = leg.DepTime,
						TicketId     = leg.TicketId
					});
				
				if (ticketId2 != null) {
					foreach (var leg in db.TicketLegs.Where(p => p.TicketId == ticketId2).ToList())
						db.InsertWithInt32Identity(new Leg {
							TripId       = tripId,
							UserId       = int.Parse(HttpContext.Session.GetString("uid")),
							TrainType    = leg.TrainType,
							TrainNr      = leg.TrainNr,
							ArrStation   = leg.ArrStation,
							ArrStationId = leg.ArrStationId,
							ArrTime      = leg.ArrTime,
							DepStation   = leg.DepStation,
							DepStationId = leg.DepStationId,
							DepTime      = leg.DepTime,
							TicketId     = leg.TicketId
						});
				}

				TripId = tripId;
			}

			else {
				var request = new XDocument(new XElement("rqorderdetails", new XAttribute("version", "1.0"),
														 new XElement("rqheader", new XAttribute("ts", "2019-10-31T23:20:48"), new XAttribute("l", "de"),
																	  new XAttribute("v", "19100000"), new XAttribute("d", "iPad7,5"),
																	  new XAttribute("os", "iOS_13.1.3"), new XAttribute("app", "NAVIGATOR")),
														 new XElement("rqorder", new XAttribute("on", Request.Query["order"])),
														 new XElement("authname", new XAttribute("tln", Request.Query["name"])))).ToString();
				var response = new WebClient().UploadString("https://fahrkarten.bahn.de/mobile/dbc/xs.go", "POST", request);
				var xmlobj   = new XmlDocument();
				xmlobj.LoadXml(response);
				var json   = JsonConvert.SerializeXmlNode(xmlobj);
				var parsed = TicketResponse.FromJson(json);

				var tripId = Request.Query["action"] == "addleg"
					? int.Parse(Request.Query["tripid"])
					: db.InsertWithInt32Identity(new Trip {UserId = int.Parse(HttpContext.Session.GetString("uid"))});

				int ticketId;
				int? ticketId2 = null;

				switch (parsed.Rporderdetails.Order.Tcklist.Tck.Count) {
					case 1: {
						ticketId = db.InsertWithInt32Identity(new Ticket {
							OrderId       = Request.Query["order"],
							TicketInfo    = parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.Txt,
							TicketQr      = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "barcode").Text,
							TicketSecCode = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "sichtmerkmal").Text,
							UserId        = int.Parse(HttpContext.Session.GetString("uid")),
							TicketPkPass  = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "pass").Text, // application/vnd.apple.pkpass;base64
							Traveller = parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.ReisenderVorname
										+ " "
										+ parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.ReisenderNachname
						});
						break;
					}
					case 2: {
						ticketId = db.InsertWithInt32Identity(new Ticket {
							OrderId       = Request.Query["order"],
							TicketInfo    = parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.Txt,
							TicketQr      = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "barcode").Text,
							TicketSecCode = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "sichtmerkmal").Text,
							UserId        = int.Parse(HttpContext.Session.GetString("uid")),
							TicketPkPass  = parsed.Rporderdetails.Order.Tcklist.Tck[0].Htdata.Ht.First(p => p.Name == "pass").Text, // application/vnd.apple.pkpass;base64
							Traveller = parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.ReisenderVorname
										+ " "
										+ parsed.Rporderdetails.Order.Tcklist.Tck[0].Mtk.ReisenderNachname
						});
						
						ticketId2 = db.InsertWithInt32Identity(new Ticket {
							OrderId       = Request.Query["order"] + "_2",
							TicketInfo    = parsed.Rporderdetails.Order.Tcklist.Tck[1].Mtk.Txt,
							TicketQr      = parsed.Rporderdetails.Order.Tcklist.Tck[1].Htdata.Ht.First(p => p.Name == "barcode").Text,
							TicketSecCode = parsed.Rporderdetails.Order.Tcklist.Tck[1].Htdata.Ht.First(p => p.Name == "sichtmerkmal").Text,
							UserId        = int.Parse(HttpContext.Session.GetString("uid")),
							TicketPkPass  = parsed.Rporderdetails.Order.Tcklist.Tck[1].Htdata.Ht.First(p => p.Name == "pass").Text, // application/vnd.apple.pkpass;base64
							Traveller = parsed.Rporderdetails.Order.Tcklist.Tck[1].Mtk.ReisenderVorname
										+ " "
										+ parsed.Rporderdetails.Order.Tcklist.Tck[1].Mtk.ReisenderNachname
						});

						break;
					}
					default: {
						throw new Exception("Order contains zero or more than two tickets");
					}
				}

				foreach (var leg in parsed.Rporderdetails.Order.Schedulelist.Out.Trainlist.Train) {
					db.InsertWithInt32Identity(new Leg {
						TripId       = tripId,
						UserId       = int.Parse(HttpContext.Session.GetString("uid")),
						TrainType    = leg.Gattung,
						TrainNr      = int.Parse(leg.Zugnummer),
						ArrStation   = leg.Arr.Name,
						ArrStationId = int.Parse(leg.Arr.BhfNr),
						ArrTime      = leg.Arr.Date.Replace("00:00:00", leg.Arr.Time),
						DepStation   = leg.Dep.Name,
						DepStationId = int.Parse(leg.Dep.BhfNr),
						DepTime      = leg.Dep.Date.Replace("00:00:00", leg.Dep.Time),
						TicketId     = ticketId
					});

					db.InsertWithInt32Identity(new TicketLeg {
						TicketId     = ticketId,
						TrainType    = leg.Gattung,
						TrainNr      = int.Parse(leg.Zugnummer),
						ArrStation   = leg.Arr.Name,
						ArrStationId = int.Parse(leg.Arr.BhfNr),
						ArrTime      = leg.Arr.Date.Replace("00:00:00", leg.Arr.Time),
						DepStation   = leg.Dep.Name,
						DepStationId = int.Parse(leg.Dep.BhfNr),
						DepTime      = leg.Dep.Date.Replace("00:00:00", leg.Dep.Time)
					});
				}

				if (parsed.Rporderdetails.Order.Schedulelist.Ret != null)
					foreach (var leg in parsed.Rporderdetails.Order.Schedulelist.Ret.Trainlist.Train) {
						db.InsertWithInt32Identity(new Leg {
							TripId       = tripId,
							UserId       = int.Parse(HttpContext.Session.GetString("uid")),
							TrainType    = leg.Gattung,
							TrainNr      = int.Parse(leg.Zugnummer),
							ArrStation   = leg.Arr.Name,
							ArrStationId = int.Parse(leg.Arr.BhfNr),
							ArrTime      = leg.Arr.Date.Replace("00:00:00", leg.Arr.Time),
							DepStation   = leg.Dep.Name,
							DepStationId = int.Parse(leg.Dep.BhfNr),
							DepTime      = leg.Dep.Date.Replace("00:00:00", leg.Dep.Time),
							TicketId     = ticketId2 ?? ticketId
						});

						db.InsertWithInt32Identity(new TicketLeg {
							TicketId     = ticketId2 ?? ticketId,
							TrainType    = leg.Gattung,
							TrainNr      = int.Parse(leg.Zugnummer),
							ArrStation   = leg.Arr.Name,
							ArrStationId = int.Parse(leg.Arr.BhfNr),
							ArrTime      = leg.Arr.Date.Replace("00:00:00", leg.Arr.Time),
							DepStation   = leg.Dep.Name,
							DepStationId = int.Parse(leg.Dep.BhfNr),
							DepTime      = leg.Dep.Date.Replace("00:00:00", leg.Dep.Time)
						});
					}

				TripId = tripId;
			}
		}
	}
}