# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

"""Java local-zone conversions used by existing schema-evolution casts."""

import pyarrow as pa

from pypaimon.utils.temporal_utils import (
    _epoch_day_to_java_date, _java_date_to_epoch_day,
    _local_offset, _local_to_utc_seconds, _signed,
)
from pypaimon.table.row.generic_row import _parse_type_precision_scale


def cast_temporal(array, target, source_type=None, target_type=None):
    timestamp = pa.types.is_timestamp(array.type)
    source_name = str(source_type).upper() if source_type is not None else ''
    ltz = timestamp and (array.type.tz is not None if source_type is None else
                         source_name.startswith('TIMESTAMP_LTZ') or 'WITH LOCAL TIME ZONE' in source_name)
    target_ts = pa.types.is_timestamp(target)
    cross = timestamp and target_ts and ltz != (target.tz is not None)
    date = pa.types.is_date32(array.type) and target_ts and target.tz is not None
    numeric = array.type == pa.int64() and target_ts and target.tz is not None
    if not (cross or date or numeric or timestamp and (pa.types.is_date32(target) or pa.types.is_time(target))):
        return None
    raw = array.cast(pa.int32() if date else pa.int64()).to_pylist()
    unit = array.type.unit if timestamp else 's'
    source_precision = (_parse_type_precision_scale(source_type)[0] if source_type is not None else
                        {'s': 0, 'ms': 3, 'us': 6, 'ns': 9}[unit] if timestamp else 0)
    target_precision = (_parse_type_precision_scale(target_type)[0] if target_type is not None else
                        {'s': 0, 'ms': 3, 'us': 6, 'ns': 9}[target.unit] if target_ts else 0)
    values = []
    for value in raw:
        if value is None:
            values.append(None)
            continue
        if date:
            millis, sub_milli = _java_date_to_epoch_day(value) * 86400000, 0
        elif unit == 's':
            millis, sub_milli = _signed(value * 1000, 64), 0
        elif unit == 'ms':
            millis, sub_milli = value, 0
        elif unit == 'us':
            millis, sub_milli = value // 1000, value % 1000 * 1000
        else:
            millis, sub_milli = value // 1000000, value % 1000000
        original = millis
        if cross and not ltz:
            millis = _signed(millis // 86400000, 32) * 86400000 + millis % 86400000
        if date or cross and not ltz:
            millis = _local_to_utc_seconds(millis // 1000) * 1000 + millis % 1000
        elif ltz or numeric:
            millis = _signed(millis + _local_offset(millis // 1000) * 1000, 64)
        if pa.types.is_date32(target):
            value = (_epoch_day_to_java_date((original + _local_offset(original // 1000) * 1000) // 86400000)
                     if ltz else _signed(millis // 86400000, 32))
        elif pa.types.is_time(target):
            value = ((original + _local_offset(original // 1000) * 1000) % 86400000
                     if ltz else millis % 86400000)
        else:
            if source_precision > target_precision:
                if target_precision <= 3:
                    quantum = 10 ** (3 - target_precision)
                    millis, sub_milli = _signed(millis // quantum * quantum, 64), 0
                else:
                    quantum = 10 ** (9 - target_precision)
                    sub_milli = sub_milli // quantum * quantum
            if target.unit == 's':
                value = millis // 1000
            elif target.unit == 'ms':
                value = millis
            elif target.unit == 'us':
                value = millis * 1000 + sub_milli // 1000
            else:
                value = millis * 1000000 + sub_milli
            if not -(1 << 63) <= value < (1 << 63):
                value = None
        values.append(value)
    if pa.types.is_time(target):
        return pa.array(values, type=pa.int32()).cast(pa.time32('ms')).cast(target, safe=False)
    return pa.array(values, type=pa.int32() if pa.types.is_date32(target) else pa.int64()).cast(target)
