Imports System.Web.Services
Imports SharePrices.SharePricesUtils

Public Class SharePrices
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Debug.Print("SharePrices - Page load - " + Now().ToString("yyyy-MM-dd HH:mm:ss") + ", IP: " + Request.UserHostAddress + ", HostName: " + Request.UserHostName)
    End Sub

    <WebMethod()>
    Public Shared Sub GetInstruments()
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.GetInstruments" + ", IP: " + HttpContext.Current.Request.UserHostAddress + ", HostName: " + HttpContext.Current.Request.UserHostName)

        Dim responseText As String = DataAccessLayer.GetInstruments()
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub

    <WebMethod()>
    Public Shared Sub AddInstrument(Symbol As String, FullName As String)
        'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.AddInstrument webmethod: " + Symbol + ", " + FullName)

        Dim responseText As String = DataAccessLayer.AddInstrument(Symbol, FullName)
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub

    '<WebMethod()>
    'Public Shared Sub UpdateInstrument(Symbol As String, GMTOffset As Integer, Currency As String, CurrentPrice As Double, InstrumentType As String)
    '    Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.UpdateInstrument webmethod: " + Symbol)

    '    DataAccessLayer.UpdateInstrument(Symbol, GMTOffset, Currency, CurrentPrice, InstrumentType)
    'End Sub

    <WebMethod()>
    Public Shared Sub AddHolding(AccountName As String, Symbol As String, NoUnits As Double, PurchasePricePerUnit As Double, PurchaseDate As Int64, PurchaseCurrency As String, BookCostInPurchaseCurrency As Double)
        'Public Shared Sub AddHolding(AccountName As String, Symbol As String, NoUnits As Integer, PurchasePricePerUnit As Double, PurchaseDate As Int64)
        'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.AddHolding webmethod: " + AccountName + ", " + Symbol)

        Dim responseText As String = DataAccessLayer.AddHolding(AccountName, Symbol, NoUnits, PurchasePricePerUnit, PurchaseDate, PurchaseCurrency, BookCostInPurchaseCurrency)
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub

    <WebMethod()>
    Public Shared Sub GetAllDailyData(startDate As Int64, endDate As Int64)
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.GetAllDailyData webmethod: """ + FromEpochTime(startDate).ToString("yyyy-MM-dd HH:mm:ss") + """, """ + FromEpochTime(endDate).ToString("yyyy-MM-dd HH:mm:ss") + """")

        Dim responseText As String = DataAccessLayer.GetAllDailyData(FromEpochTime(startDate), FromEpochTime(endDate))
        If responseText = "" Then responseText = "[]"
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.GetAllDailyData finished")
    End Sub

    <WebMethod()>
    Public Shared Sub GetDailyData(Symbol As String, startDate As Int64, endDate As Int64)
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.GetDailyData webmethod: """ + Symbol + """, """ + FromEpochTime(startDate).ToString("yyyy-MM-dd HH:mm:ss") + """, """ + FromEpochTime(endDate).ToString("yyyy-MM-dd HH:mm:ss") + """")

        Dim responseText As String = DataAccessLayer.GetDailyData(Symbol, FromEpochTime(startDate), FromEpochTime(endDate))
        If responseText = "" Then responseText = "[]"
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.GetDailyData finished")
    End Sub

    <WebMethod()>
    Public Shared Sub GetAllIntradayData(startDate As Int64, endDate As Int64)
        Dim startDT As Date = Now()
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.GetAllIntradayData webmethod: """ + FromEpochTime(startDate).ToString("yyyy-MM-dd HH:mm:ss") + """, """ + FromEpochTime(endDate).ToString("yyyy-MM-dd HH:mm:ss") + """")

        Dim responseText As String = DataAccessLayer.GetAllIntradayData(FromEpochTime(startDate), FromEpochTime(endDate))
        If responseText = "" Then responseText = "[]"
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
        Dim endDT As Date = Now()
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.GetAllIntradayData completed. Duration = " + DateDiff(DateInterval.Second, startDT, endDT).ToString())
    End Sub

    <WebMethod()>
    Public Shared Sub GetIntradayData(Symbol As String, startDate As Int64, endDate As Int64)
        'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.GetIntradayData webmethod: """ + Symbol + """, """ + FromEpochTime(startDate).ToString("yyyy-MM-dd HH:mm:ss") + """, """ + FromEpochTime(endDate).ToString("yyyy-MM-dd HH:mm:ss") + """")

        Dim responseText As String = DataAccessLayer.GetIntradayData(Symbol, FromEpochTime(startDate), FromEpochTime(endDate))
        If responseText = "" Then responseText = "[]"
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub

    <WebMethod()>
    Public Shared Sub SubmitDailyData(Symbol As String, DailyPrices As List(Of DataAccessLayer.PriceData))
        Dim startDT As Date = Now()
        'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.SubmitDailyData webmethod: " + Symbol)

        Try
            Dim responseText As String = DataAccessLayer.InsertDailyData(Symbol, DailyPrices)
            If responseText = "" Then responseText = "[]"
            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
            
            'If Symbol = "RYA.L" Then
            '    For Each pd As DataAccessLayer.PriceData In DailyPrices
            '        Debug.Print("    " + FromEpochTime(pd.DT))
            '    Next
            '    Debug.Print("   Response: " + responseText)
            'End If
        Catch ex As Exception
            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", "{""Result"":""Error""}")
        End Try

        Dim endDT As Date = Now()
        'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.SubmitDailyData(" + Symbol + ") completed. Duration = " + DateDiff(DateInterval.Second, startDT, endDT).ToString())
    End Sub

    <WebMethod()>
    Public Shared Sub SubmitIntradayData(Symbol As String, DailyPrices As List(Of DataAccessLayer.PriceData), GMTOffset As Integer, Currency As String, CurrentPrice As Double, InstrumentType As String, TradeDayStart As Long, TradeDayEnd As Long)
        'Public Shared Sub SubmitIntradayData(Symbol As String, DailyPrices As List(Of DataAccessLayer.PriceData))
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.SubmitIntradayData webmethod: " + Symbol)

        DataAccessLayer.UpdateInstrument(Symbol, GMTOffset, Currency, CurrentPrice, InstrumentType, FromEpochTime(TradeDayStart), FromEpochTime(TradeDayEnd))

        Dim responseText As String = DataAccessLayer.InsertIntradayData(Symbol, DailyPrices)
        If responseText = "" Then responseText = "[]"
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub

    <WebMethod()>
    Public Shared Sub SwapInstrumentDisplayOrders(Symbol1 As String, Symbol2 As String)
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.SwapInstrumentDisplayOrders webmethod: " + Symbol1 + ", " + Symbol2)

        Dim responseText As String = DataAccessLayer.SwapInstrumentDisplayOrders(Symbol1, Symbol2)
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub

    '<WebMethod()>
    'Public Shared Sub DeleteHolding(HoldingID As Integer)
    '    'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.DeleteHolding webmethod: " + HoldingID.ToString())

    '    Dim responseText As String = DataAccessLayer.DeleteHolding(HoldingID)
    '    SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    'End Sub
    <WebMethod()>
    Public Shared Sub SoldHolding(HoldingID As Integer, SoldDate As Int64, SoldCurrency As String, SoldProceeds As Double)
        'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.SoldHolding webmethod: " + HoldingID.ToString() + ". " + SoldDate.TYoString())

        Dim responseText As String = DataAccessLayer.SoldHolding(HoldingID, FromEpochTime(SoldDate), SoldCurrency, SoldProceeds)
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub

    <WebMethod()>
    Public Shared Sub SetAccountCashValue(AccountName As String, Currency As String, Value As Double)
        Dim responseText As String = DataAccessLayer.SetAccountCashValue(AccountName, Currency, Value)
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub

    Private Shared Function DownloadYahooFinanceWebString(queryString As String) As String
        Dim webClient As New System.Net.WebClient()

        'webClient.Proxy = New System.Net.WebProxy("127.0.0.1", 8888)

        'Set headers required by Yahoo Finance
        webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0")
        webClient.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
        webClient.Headers.Add("Accept-Language", "en-GB,en;q=0.5")
        'webClient.Headers.Add("Accept-Encoding", "gzip, deflate, br")
        'Connection: keep -alive
        webClient.Headers.Add("Upgrade-Insecure-Requests", "1")
        webClient.Headers.Add("Sec-Fetch-Dest", "document()")
        webClient.Headers.Add("Sec-Fetch-Mode", "navigate()")
        webClient.Headers.Add("Sec-Fetch-Site", "none()")
        webClient.Headers.Add("Sec-Fetch-User", "?1")

        DownloadYahooFinanceWebString = webClient.DownloadString(queryString)
    End Function
    <WebMethod()>
    Public Shared Sub FetchYahooFinanceIntraday(Symbol As String)
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.FetchYahooFinanceIntraday webmethod: " + Symbol)

        'Dim webClient As New System.Net.WebClient
        'webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36")
        'webClient.Headers.Add("Cookie", "GUC=AQABCAFlwl1l7kIazgRS&s=AQAAAIC-LaMs&g=ZcEX6w; A1=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; A3=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; A1S=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; EuConsent=CP325IAP325IAAOACKENAqEgAAAAAAAAACiQAAAAAAAA; thamba=2; PRF=t%3DMSTR%252BSHIB-GBP%252BGBPAUD%253DX%252BCOIN%252BAMZN%252BRIOT%252BLMI3.L%252BFLT.AX%252BAAL%252BMKS.L%252BMSFT%252BLUNC-USD%252B3LMI.L%252BNCLH%252B3MIB.MI%26newChartbetateaser%3D1%26qct%3DtrendArea; cmp=t=1709739374&j=1&u=1---&v=16")
        'Dim responseText As String = webClient.DownloadString("https://query1.finance.yahoo.com/v8/finance/chart/" + Symbol + "?region=GB&lang=en-GB&includePrePost=false&interval=1h&range=1mo&.tsrc=finance")

        Dim responseText As String = DownloadYahooFinanceWebString("https://query1.finance.yahoo.com/v8/finance/chart/" + Symbol + "?region=GB&lang=en-GB&includePrePost=false&interval=1h&range=1mo&.tsrc=finance")

        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub
    <WebMethod()>
    Public Shared Sub FetchYahooFinanceIntraday(Symbol As String, MinIntradayDT As Long)
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.FetchYahooFinanceIntraday webmethod: " + Symbol + ", " + MinIntradayDT.ToString() + " (" + FromEpochTime(MinIntradayDT).ToString("yyyy-MM-dd HH:mm") + ")")

        Try
            Dim queryString As String

            If MinIntradayDT <= ToEpochTime(Now().AddDays(-59)) Then 'Yahoo finance only provides 15min data for previous 60 days
                queryString = "https://query1.finance.yahoo.com/v8/finance/chart/" + Symbol + "?region=GB&lang=en-GB&includePrePost=false&interval=15m&range=1mo&.tsrc=finance"
            Else
                Dim dateTo As Long
                If MinIntradayDT > 9999999999 Then
                    dateTo = Math.Ceiling(MinIntradayDT / 1000)
                Else
                    dateTo = MinIntradayDT
                End If
                Dim dateFrom As Long = dateTo - (15 * (60 * 60 * 24)) '15 days
                'Need to make sure dateFrom is no more than 60 days ago
                Dim minAllowableDate = Math.Floor(ToEpochTime(Now().AddDays(-59)) / 1000) - 60
                If dateFrom < minAllowableDate Then
                    dateFrom = minAllowableDate
                End If
                queryString = "https://query1.finance.yahoo.com/v8/finance/chart/" + Symbol + "?period1=" + dateFrom.ToString() + "&period2=" + dateTo.ToString() + "&interval=15m&includePrePost=true&events=div|split|earn"
            End If
            
            Debug.Print(Strings.StrDup(22, " ") + queryString)

            'Dim webClient As New System.Net.WebClient
            'webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36")
            'webClient.Headers.Add("Cookie", "GUC=AQABCAFlwl1l7kIazgRS&s=AQAAAIC-LaMs&g=ZcEX6w; A1=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; A3=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; A1S=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; EuConsent=CP325IAP325IAAOACKENAqEgAAAAAAAAACiQAAAAAAAA; thamba=2; PRF=t%3DMSTR%252BSHIB-GBP%252BGBPAUD%253DX%252BCOIN%252BAMZN%252BRIOT%252BLMI3.L%252BFLT.AX%252BAAL%252BMKS.L%252BMSFT%252BLUNC-USD%252B3LMI.L%252BNCLH%252B3MIB.MI%26newChartbetateaser%3D1%26qct%3DtrendArea; cmp=t=1709739374&j=1&u=1---&v=16")
            'Dim responseText As String = webClient.DownloadString(queryString)

            Dim responseText As String = DownloadYahooFinanceWebString(queryString)

            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
        Catch ex As Exception
            Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - ERROR - SharePrices.FetchYahooFinanceIntraday webmethod: " + Symbol + ", " + MinIntradayDT.ToString() + " (" + FromEpochTime(MinIntradayDT).ToString("yyyy-MM-dd") + "): " + ex.Message)
            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", "{""Result"":""Error"", ""MSG"":""" + ex.Message.Replace("""", "'") + """}")
        End Try
    End Sub

    <WebMethod()>
    Public Shared Sub FetchYahooFinanceDaily(Symbol As String)
        'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.FetchYahooFinanceDaily webmethod: " + Symbol)

        'If Symbol = "RYA.L" Then
        '    Debug.Print(" FetchYahooFinanceDaily")
        'End If

        Try
            'Dim webClient As New System.Net.WebClient
            'webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36")
            'webClient.Headers.Add("Cookie", "GUC=AQABCAFlwl1l7kIazgRS&s=AQAAAIC-LaMs&g=ZcEX6w; A1=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; A3=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; A1S=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; EuConsent=CP325IAP325IAAOACKENAqEgAAAAAAAAACiQAAAAAAAA; thamba=2; PRF=t%3DMSTR%252BSHIB-GBP%252BGBPAUD%253DX%252BCOIN%252BAMZN%252BRIOT%252BLMI3.L%252BFLT.AX%252BAAL%252BMKS.L%252BMSFT%252BLUNC-USD%252B3LMI.L%252BNCLH%252B3MIB.MI%26newChartbetateaser%3D1%26qct%3DtrendArea; cmp=t=1709739374&j=1&u=1---&v=16")
            'Dim responseText As String = webClient.DownloadString("https://query1.finance.yahoo.com/v8/finance/chart/" + Symbol + "?region=GB&lang=en-GB&includePrePost=false&interval=1d&range=6mo&.tsrc=finance")

            Dim responseText As String = DownloadYahooFinanceWebString("https://query1.finance.yahoo.com/v8/finance/chart/" + Symbol + "?region=GB&lang=en-GB&includePrePost=false&interval=1d&range=6mo&.tsrc=finance")
            
            'If Symbol = "RYA.L" Then
            '    Debug.Print(" FetchYahooFinanceDaily result: " + responseText)
            'End If
            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
        Catch ex As Exception
            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", "{""Result"":""Error""}")
        End Try
    End Sub
    <WebMethod()>
    Public Shared Sub FetchYahooFinanceDaily(Symbol As String, MinDailyDT As Long)
        'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.FetchYahooFinanceDaily webmethod: " + Symbol + ", " + MinDailyDT.ToString() + " (" + FromEpochTime(MinDailyDT).ToString("yyyy-MM-dd") + ")")

        Try
            Dim queryString As String

            If MinDailyDT <= ToEpochTime(Now().AddYears(-2)) Then
                queryString = "https://query1.finance.yahoo.com/v8/finance/chart/" + Symbol + "?region=GB&lang=en-GB&includePrePost=false&interval=1d&range=6mo&.tsrc=finance"
            Else
                queryString = "https://query1.finance.yahoo.com/v8/finance/chart/" + Symbol + "?region=GB&lang=en-GB&includePrePost=false&interval=1d&range=2y&.tsrc=finance"
            End If

            'Dim webClient As New System.Net.WebClient()
            'webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36")
            'webClient.Headers.Add("Cookie", "GUC=AQABCAFlwl1l7kIazgRS&s=AQAAAIC-LaMs&g=ZcEX6w; A1=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; A3=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; A1S=d=AQABBKsFOF4CEKgz-h7IBcA5SkDmxV7-I5sFEgABCAFdwmXuZfbPb2UBAiAAAAcI0629W8qjNBE&S=AQAAAovZo-67b5pxvVWHK4xGTFo; EuConsent=CP325IAP325IAAOACKENAqEgAAAAAAAAACiQAAAAAAAA; thamba=2; PRF=t%3DMSTR%252BSHIB-GBP%252BGBPAUD%253DX%252BCOIN%252BAMZN%252BRIOT%252BLMI3.L%252BFLT.AX%252BAAL%252BMKS.L%252BMSFT%252BLUNC-USD%252B3LMI.L%252BNCLH%252B3MIB.MI%26newChartbetateaser%3D1%26qct%3DtrendArea; cmp=t=1709739374&j=1&u=1---&v=16")
            'Dim responseText As String = webClient.DownloadString(queryString)

            Dim responseText As String = DownloadYahooFinanceWebString(queryString)

            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
        Catch ex As Exception
            'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - ERROR - SharePrices.FetchYahooFinanceDaily webmethod: " + Symbol + ", " + MinDailyDT.ToString() + " (" + FromEpochTime(MinDailyDT).ToString("yyyy-MM-dd") + "): " + ex.Message)
            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", "{""Result"":""Error"", ""MSG"":""" + ex.Message.Replace("""", "'") + """}")
        End Try
    End Sub

    <WebMethod()>
    Public Shared Sub FetchYahooFinanceSingleDay(Symbol As String)
        'Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.FetchYahooFinanceSingleDay webmethod: " + Symbol)

        Try
            'Dim webClient As New System.Net.WebClient
            'Dim responseText As String = webClient.DownloadString("https://query1.finance.yahoo.com/v8/finance/chart/" + Symbol + "?region=GB&lang=en-GB&includePrePost=false&interval=2m&range=1d&corsDomain=uk.finance.yahoo.com&.tsrc=finance")
            Dim responseText As String = DownloadYahooFinanceWebString("https://query1.finance.yahoo.com/v8/finance/chart/" + Symbol + "?region=GB&lang=en-GB&includePrePost=false&interval=2m&range=1d&corsDomain=uk.finance.yahoo.com&.tsrc=finance")
            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
        Catch ex As Exception
            Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - ERROR - SharePrices.FetchYahooFinanceSingleDay webmethod: " + Symbol + "): " + ex.Message)
            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", "{""Result"":""Error"", ""MSG"":""" + ex.Message.Replace("""", "'") + """}")
        End Try
    End Sub

    Private Shared lseToken As String = ""
    Private Shared lseTokenLastUpdated = New DateTime(2000, 1, 1)
    Private Shared lseTokenUpdateIntervalMins = 5
    Private Shared Function DownloadLseWebString(queryString As String) As String
        If lseToken = "" Or lseTokenLastUpdated < Now().AddMinutes(0 - lseTokenUpdateIntervalMins) Then
            Dim wc As New System.Net.WebClient()
            wc.Headers.Add("Dnt", "1")
            wc.Headers.Add("Sid", "98b738c5-9d73-4d18-9329-7e248a2c7d16")
            'lseToken = wc.DownloadString("https://refinitiv-widgets.financial.com/auth/api/v1/tokens")
            lseToken = wc.UploadString("https://refinitiv-widgets.financial.com/auth/api/v1/tokens", "POST", "")
            lseTokenLastUpdated = Now()
            Debug.Print("New LSE Token: " + lseToken)
        Else
            Debug.Print("Reusing LSE Token: " + lseToken)
        End If

        Dim webClient As New System.Net.WebClient()

        'Set headers required by LondonStockExchange.com
        'Dim Quote As String = Chr(34)
        'webClient.Headers.Add(":authority", "refinitiv-widgets.financial.com")
        'webClient.Headers.Add(":method", "GET")
        'webClient.Headers.Add(":path", "/rest/api/timeseries/tns?ric=LMI3.L&fids=0,0,6,8993,178,6,tns.-103,44&count=100&__ts=1711471848806")
        'webClient.Headers.Add(":scheme", "https")
        'webClient.Headers.Add("Accept", "application/json")
        'webClient.Headers.Add("Accept-Encoding", "gzip, deflate, br, zstd")
        'webClient.Headers.Add("Accept-Language", "en-US,en;q=0.9")
        'webClient.Headers.Add("Cache-Control", "no-cache")
        webClient.Headers.Add("Dnt", "1")
        'webClient.Headers.Add("Jwt", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZ24iOiJXR19MU0VHIiwibmJmIjoxNzExNDcxODQzLCJwcnQiOiJ3bGliX0xTRUciLCJpc3MiOiJmaW5jb20iLCJwcm0iOlsiYTpzdHJlYW1pbmciLCJVU0VSIl0sImV0eSI6IldHX0xTRUciLCJleHAiOjE3MTE0NzIxNDgsImlhdCI6MTcxMTQ3MTg0OCwianRpIjoiODE4ZDQxZDktMThjZS00MGVjLWFkMzEtODk1NjRiYTlkMmY3IiwiZGlkIjoiV0dfTFNFRyIsInNlYSI6ImIwNTc5ZjczLWUxZjYtNDExZS1hYjk1LWNjZTYyNmY5OTJmZCJ9.cLv4uKzKLL4FmzMSljecOdN_0R5be1xOicOYw_WNvY0")
        webClient.Headers.Add("Jwt", lseToken)
        'webClient.Headers.Add("Origin", "https://www.londonstockexchange.com")
        'webClient.Headers.Add("Pragma", "no-cache")
        'webClient.Headers.Add("Referer", "https://www.londonstockexchange.com/")
        'webClient.Headers.Add("Sec-Ch-Ua", Quote + "Google Chrome" + Quote + ";v=" + Quote + "123" + Quote + ", " + Quote + "Not:A-Brand" + Quote + ";v=" + Quote + "8" + Quote + ", " + Quote + "Chromium" + Quote + ";v=" + Quote + "123" + Quote)
        'webClient.Headers.Add("Sec-Ch-Ua-Mobile", "?0")
        'webClient.Headers.Add("Sec-Ch-Ua-Platform", Quote + "Windows" + Quote)
        'webClient.Headers.Add("Sec-Fetch-Dest", "empty")
        'webClient.Headers.Add("Sec-Fetch-Mode", "cors")
        'webClient.Headers.Add("Sec-Fetch-Site", "cross-site")
        webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36")

        DownloadLseWebString = webClient.DownloadString(queryString)
    End Function
    <WebMethod()>
    Public Shared Sub FetchLseSingleDay(Symbol As String, FromDate As Long, ToDate As Long)
        'https://refinitiv-widgets.financial.com/rest/api/timeseries/tns?ric=LMI3.L&fids=0,0,6,8993,178,6,tns.-103,44&fromDate=1711440000000&toDate=1711469220000&count=100&__ts=1711469273221

        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.FetchLseSingleDay webmethod: " + Symbol + ", " + FromDate.ToString() + " (" + FromEpochTime(FromDate).ToString("yyyy-MM-dd HH:mm") + "), " + ToDate.ToString() + " (" + FromEpochTime(ToDate).ToString("yyyy-MM-dd HH:mm") + ")")

        Try
            Dim queryString As String

            queryString = "https://refinitiv-widgets.financial.com/rest/api/timeseries/tns?ric=" + Symbol + "&fids=0,0,6,8993,178,6,tns.-103,44&fromDate=" + FromDate.ToString() + "&toDate=" + ToDate.ToString() + "&count=1000" '"&__ts=1711469273221"

            Debug.Print(Strings.StrDup(22, " ") + queryString)

            Dim responseText As String = DownloadLseWebString(queryString)

            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
        Catch ex As Exception
            Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - ERROR - SharePrices.FetchLseSingleDay webmethod: " + Symbol + ", " + FromDate.ToString() + " (" + FromEpochTime(FromDate).ToString("yyyy-MM-dd HH:mm") + "), " + ToDate.ToString() + " (" + FromEpochTime(ToDate).ToString("yyyy-MM-dd HH:mm") + "): " + ex.Message)
            SetResponseAndCompleteRequest(HttpContext.Current, "application/json", "{""Result"":""Error"", ""MSG"":""" + ex.Message.Replace("""", "'") + """}")
        End Try
    End Sub

    <WebMethod()>
    Public Shared Sub SearchYahooFinanceShares(SearchString As String)
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.SearchYahooFinanceShares webmethod: " + SearchString)

        Dim webClient As New System.Net.WebClient

        webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0")
        webClient.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
        webClient.Headers.Add("Accept-Language", "en-GB,en;q=0.5")
        'webClient.Headers.Add("Accept-Encoding", "gzip, deflate, br")
        'Connection: keep -alive
        webClient.Headers.Add("Upgrade-Insecure-Requests", "1")
        webClient.Headers.Add("Sec-Fetch-Dest", "document()")
        webClient.Headers.Add("Sec-Fetch-Mode", "navigate()")
        webClient.Headers.Add("Sec-Fetch-Site", "none()")
        webClient.Headers.Add("Sec-Fetch-User", "?1")

        Dim responseText As String = webClient.DownloadString("https://query1.finance.yahoo.com/v1/finance/search?q=" + SearchString + "&quotesCount=6&newsCount=0&enableFuzzyQuery=false&quotesQueryId=tss_match_phrase_query&multiQuoteQueryId=multi_quote_single_token_query&newsQueryId=news_ss_symbols&enableCb=false&enableNavLinks=false&vespaNewsTimeoutMs=600")
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub

    <WebMethod()>
    Public Shared Sub SetTotalHoldingsValue(TotalValue As Double)
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.SetTotalHoldingsValue webmethod: " + CStr(TotalValue))

        Dim responseText As String = DataAccessLayer.SetTotalHoldingsValues(TotalValue)
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub

    <WebMethod()>
    Public Shared Sub GetTotalHoldingsHistory()
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.GetTotalHoldingsHistory")

        Dim responseText As String = DataAccessLayer.GetTotalHoldingsHistory()
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", responseText)
    End Sub







    <WebMethod()>
    Public Shared Sub TestWebMethod(Symbol As String, DailyPrices As List(Of DataAccessLayer.PriceData))
        Dim startDT As Date = Now()
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.TestWebMethod: " + Symbol)

        While startDT.AddSeconds(1) > Now()
            System.Threading.Thread.Sleep(100)
        End While
        SetResponseAndCompleteRequest(HttpContext.Current, "application/json", "{""Result"": ""OK - " + Symbol + """}")

        Dim endDT As Date = Now()
        Debug.Print(Now().ToString("yyyy-MM-dd HH:mm:ss") + " - SharePrices.TestWebMethod(" + Symbol + ") completed. Duration = " + DateDiff(DateInterval.Second, startDT, endDT).ToString())
    End Sub

End Class