module fortplot_twin_axes_rendering
    !! Twin axes label rendering for raster, PDF, and ASCII backends
    !! Extracted from fortplot_figure_rendering_pipeline for size compliance (Issue #1747)

    use, intrinsic :: iso_fortran_env, only: wp => real64
    use fortplot_context, only: plot_context
    use fortplot_raster, only: raster_context
    use fortplot_ascii, only: ascii_context
    use fortplot_ascii_secondary_axes, only: ascii_draw_secondary_y_axis, &
                                             ascii_draw_secondary_x_axis_top
    use fortplot_raster_axes, only: raster_draw_secondary_y_axis, &
                                    raster_draw_secondary_x_axis_top
    implicit none

    private
    public :: setup_twin_axes_state
    public :: render_twin_labels

    character(len=16), parameter :: DEFAULT_SCALE = 'linear          '

contains

    subroutine setup_twin_axes_state(has_twinx, has_twiny, twinx_y_min, twinx_y_max, &
                                     twiny_x_min, twiny_x_max, twinx_yscale, &
                                     twiny_xscale, twinx_ylabel, twiny_xlabel, &
                                     xscale, yscale, has_twinx_local, has_twiny_local, &
                                     twinx_y_min_local, twinx_y_max_local, &
                                     twiny_x_min_local, twiny_x_max_local, &
                                     twinx_scale_local, twiny_scale_local)
        !! Setup local state for twin axes configuration
        logical, intent(in), optional :: has_twinx, has_twiny
        real(wp), intent(in), optional :: twinx_y_min, twinx_y_max
        real(wp), intent(in), optional :: twiny_x_min, twiny_x_max
        character(len=*), intent(in), optional :: twinx_yscale, twiny_xscale
        character(len=:), allocatable, intent(in), optional :: twinx_ylabel, &
                                                               twiny_xlabel
        character(len=*), intent(in) :: xscale, yscale
        logical, intent(out) :: has_twinx_local, has_twiny_local
        real(wp), intent(out) :: twinx_y_min_local, twinx_y_max_local
        real(wp), intent(out) :: twiny_x_min_local, twiny_x_max_local
        character(len=16), intent(out) :: twinx_scale_local, twiny_scale_local

        has_twinx_local = .false.
        has_twiny_local = .false.
        twinx_scale_local = DEFAULT_SCALE
        twiny_scale_local = DEFAULT_SCALE

        if (present(has_twinx)) then
            has_twinx_local = has_twinx
            if (has_twinx_local) then
                if (present(twinx_y_min) .and. present(twinx_y_max)) then
                    twinx_y_min_local = twinx_y_min
                    twinx_y_max_local = twinx_y_max
                else
                    has_twinx_local = .false.
                end if
                if (has_twinx_local .and. present(twinx_yscale)) twinx_scale_local = &
                    trim(twinx_yscale)//repeat(' ', 16 - len_trim(twinx_yscale))
            end if
        end if

        if (present(has_twiny)) then
            has_twiny_local = has_twiny
            if (has_twiny_local) then
                if (present(twiny_x_min) .and. present(twiny_x_max)) then
                    twiny_x_min_local = twiny_x_min
                    twiny_x_max_local = twiny_x_max
                else
                    has_twiny_local = .false.
                end if
                if (has_twiny_local .and. present(twiny_xscale)) twiny_scale_local = &
                    trim(twiny_xscale)//repeat(' ', 16 - len_trim(twiny_xscale))
            end if
        end if
    end subroutine setup_twin_axes_state

    subroutine render_twin_labels(backend, xscale, yscale, symlog_threshold, &
                                  x_min, x_max, y_min, y_max, title, xlabel, &
                                  ylabel, custom_xticks, custom_xtick_labels, &
                                  custom_yticks, custom_ytick_labels, &
                                  has_twinx_local, has_twiny_local, &
                                  twinx_scale_local, twiny_scale_local, &
                                  twinx_y_min_local, twinx_y_max_local, &
                                  twiny_x_min_local, twiny_x_max_local, &
                                  x_date_format, y_date_format, &
                                  twinx_y_date_format, twiny_x_date_format, &
                                  twinx_ylabel, twiny_xlabel, draw_primary_labels)
        !! Render labels for all backend types (raster, PDF, ASCII)
        use fortplot_pdf, only: pdf_context
        class(plot_context), intent(inout) :: backend
        character(len=*), intent(in) :: xscale, yscale
        real(wp), intent(in) :: symlog_threshold
        real(wp), intent(in) :: x_min, x_max, y_min, y_max
        character(len=:), allocatable, intent(in) :: title, xlabel, ylabel
        real(wp), intent(in), optional :: custom_xticks(:), custom_yticks(:)
        character(len=*), intent(in), optional :: custom_xtick_labels(:)
        character(len=*), intent(in), optional :: custom_ytick_labels(:)
        character(len=*), intent(in), optional :: x_date_format, y_date_format
        character(len=*), intent(in), optional :: twinx_y_date_format, &
                                                  twiny_x_date_format
        logical, intent(in) :: has_twinx_local, has_twiny_local
        real(wp), intent(in) :: twinx_y_min_local, twinx_y_max_local
        real(wp), intent(in) :: twiny_x_min_local, twiny_x_max_local
        character(len=16), intent(in) :: twinx_scale_local, twiny_scale_local
        character(len=:), allocatable, intent(in), optional :: twinx_ylabel, &
                                                               twiny_xlabel
        logical, intent(in), optional :: draw_primary_labels
        logical :: draw_primary_labels_local

        draw_primary_labels_local = .true.
        if (present(draw_primary_labels)) draw_primary_labels_local = &
            draw_primary_labels

        select type (backend)
        class is (raster_context)
            if (draw_primary_labels_local) then
                call backend%draw_axis_labels_only(xscale, yscale, &
                                                   symlog_threshold, &
                                                   x_min, x_max, y_min, y_max, &
                                                   title, xlabel, ylabel, &
                                                   custom_xticks, &
                                                   custom_xtick_labels, &
                                                   custom_yticks, &
                                                   custom_ytick_labels, &
                                                   x_date_format=x_date_format, &
                                                   y_date_format=y_date_format)
            end if

            if (has_twinx_local) then
                if (present(twinx_ylabel)) then
                    call raster_draw_secondary_y_axis( &
                        backend%raster, backend%width, backend%height, &
                        backend%plot_area, &
                        twinx_scale_local, symlog_threshold, twinx_y_min_local, &
                        twinx_y_max_local, ylabel=twinx_ylabel, &
                        date_format=twinx_y_date_format)
                else
                    call raster_draw_secondary_y_axis( &
                        backend%raster, backend%width, backend%height, &
                        backend%plot_area, &
                        twinx_scale_local, symlog_threshold, twinx_y_min_local, &
                        twinx_y_max_local, date_format=twinx_y_date_format)
                end if
            end if

            if (has_twiny_local) then
                if (present(twiny_xlabel)) then
                    call raster_draw_secondary_x_axis_top( &
                        backend%raster, backend%width, backend%height, &
                        backend%plot_area, &
                        twiny_scale_local, symlog_threshold, twiny_x_min_local, &
                        twiny_x_max_local, xlabel=twiny_xlabel, &
                        date_format=twiny_x_date_format)
                else
                    call raster_draw_secondary_x_axis_top( &
                        backend%raster, backend%width, backend%height, &
                        backend%plot_area, &
                        twiny_scale_local, symlog_threshold, twiny_x_min_local, &
                        twiny_x_max_local, date_format=twiny_x_date_format)
                end if
            end if

        class is (pdf_context)
            if (has_twinx_local) then
                call backend%draw_secondary_y_axis( &
                    twinx_scale_local, symlog_threshold, twinx_y_min_local, &
                    twinx_y_max_local, twinx_ylabel, &
                    date_format=twinx_y_date_format)
            end if

            if (has_twiny_local) then
                call backend%draw_secondary_x_axis_top( &
                    twiny_scale_local, symlog_threshold, twiny_x_min_local, &
                    twiny_x_max_local, twiny_xlabel, &
                    date_format=twiny_x_date_format)
            end if

        class is (ascii_context)
            if (has_twinx_local) then
                call ascii_draw_secondary_y_axis(backend, twinx_scale_local, &
                               symlog_threshold, twinx_y_min_local, twinx_y_max_local, &
                                          twinx_ylabel, date_format=twinx_y_date_format)
            end if

            if (has_twiny_local) then
                call ascii_draw_secondary_x_axis_top(backend, twiny_scale_local, &
                               symlog_threshold, twiny_x_min_local, twiny_x_max_local, &
                                          twiny_xlabel, date_format=twiny_x_date_format)
            end if
        end select
    end subroutine render_twin_labels

end module fortplot_twin_axes_rendering
